代码之家  ›  专栏  ›  技术社区  ›  Benjamin Ortuzar

json.net到c对象

  •  7
  • Benjamin Ortuzar  · 技术社区  · 16 年前

    我试图使用Windows窗体中的json.net框架从json字符串中读取一些信息。但我正努力从“分类法->主题”数组和“群集”中获取字典。

    {
        "keywords": {
            "anyString": [
    
            ],
            "allString": {
                "a5349f533e3aa3ccbc27de2638da38d6": "olympics"
            },
            "exactString": [
    
            ],
            "notString": [
    
            ],
            "highlightString": [
    
            ]
        },
        "dates": {
            "startDate": "15-01-2008",
            "endDate": "15-09-2009",
            "useDates": true
        },
        "clusters": {
            "permission": {
                "1": "private\/n"
            }
        },
        "taxonomies": {
            "Topics": {
                "2488": "Olympics 2012 (not participation)",
                "8876": "Olympics and culture"
            },
            "Keywords": {
                "8848": "Engineering in the Olympics"
            }
        },
        "sort": {
            "sortId": 1,
            "sortType": 2,
            "sort": "datetime",
            "sortOrder": "descending"
        }
    }
    

    通过下面的代码,我已经能够阅读一些信息。

    JObject searchCriteria = JObject.Parse(contentSearchCriteria);  
    //search criteria   
    IEnumerable<string> allString = searchCriteria["keywords"]["allString"].Children().Values<string>();
    IEnumerable<string> anyString = searchCriteria["keywords"]["anyString"].Children().Values<string>();
    IEnumerable<string> notString = searchCriteria["keywords"]["notString"].Children().Values<string>();
    IEnumerable<string> exactString = searchCriteria["keywords"]["exactString"].Children().Values<string>();
    IEnumerable<string> highlightString = searchCriteria["keywords"]["highlightString"].Children().Values<string>();
    //dates
    string startDate = (string)searchCriteria["dates"]["startDate"];
    string endDate = (string)searchCriteria["dates"]["endDate"];
    bool useDates = (bool)searchCriteria["dates"]["useDates"];
    
    //sort
    int sortId = (int)searchCriteria["sort"]["sortId"];
    int sortType = (int)searchCriteria["sort"]["sortType"];
    string sort = (string)searchCriteria["sort"]["sort"];
    string sortOrder = (string)searchCriteria["sort"]["sortOrder"];
    

    更新:

    正如我所建议的那样

    class SMSearchCriteria
        {
            public SMKeywords keywords { get; set; }
            public SMDates dates { get; set; }
            public SMClusters clusters { get; set; }
            public SMTaxonomies taxonomies { get; set; }
            public SMSort sort { get; set; }
        }
    
        class SMKeywords
        {
            public List<Dictionary<string, string>> AnyString {get; set;}
            public List<Dictionary<string, string>> AllString { get; set; }
            public List<Dictionary<string, string>> ExactString { get; set; }
            public List<Dictionary<string, string>> NotString { get; set; }
            public List<Dictionary<string, string>> HighlightString { get; set; } 
        }
    
        class SMDates
        {
            public string startDate { get; set; }
            public string endDate { get; set; }
            public bool useDates { get; set; }
        }
    
        class SMClusters
        {
            List<SMCluster> cluster;
        }
    
        class SMCluster
        {
            public Dictionary<string, string> cluster { get; set; }
        }
    
         class SMTaxonomies
        {
             public List<SMTaxonomy> taxonomies { get; set; }
        }
    
         class SMTaxonomy
         {
             public Dictionary<string, List<SMCategory>> taxonomy { get; set; }
         }
    
         class SMCategory
         {
             public Dictionary<int, string> category { get; set; }
         }
    
         class SMSort
        {
            public int sortId { get; set; }
            public int sortType { get; set; }
            public string sort { get; set; }
            public string sortOrder { get; set; }
        }
    

    但当我执行时:

        var mydata = JsonConvert.DeserializeObject<SMSearchCriteria>(contentSearchCriteria);
    

    我得到例外:

    [Newtonsoft.Json.JsonSerializationException] = {"Cannot deserialize JSON object into type 'System.Collections.Generic.List`1[System.Collections.Generic.Dictionary`2[System.String,System.String]]'."}
    

    更新2:

    按照建议,我删除了所有额外的列表,并将类简化为:

    class SearchMasterSearchCriteria
        {
            public SMKeywords keywords { get; set; }
            public SMDates dates { get; set; }
            public Dictionary<string, Dictionary<int, string>> clusters { get; set; } 
            public Dictionary<string, Dictionary<int, string>> taxonomies { get; set; } 
            public SMSort sort { get; set; }
        }
    
        class SMKeywords
        {
            public Dictionary<string, string> anyString {get; set;}
            public Dictionary<string, string> allString { get; set; }
            public Dictionary<string, string> exactString { get; set; }
            public Dictionary<string, string> notString { get; set; }
            public Dictionary<string, string> highlightString { get; set; } 
        }
    
        class SMDates
        {
            public string startDate { get; set; }
            public string endDate { get; set; }
            public bool useDates { get; set; }
        }
    
         class SMSort
        {
            public int sortId { get; set; }
            public int sortType { get; set; }
            public string sort { get; set; }
            public string sortOrder { get; set; }
        }
    

    我还添加了测试代码来序列化这样的对象:

    //criteria
                SearchMasterSearchCriteria smCriteria = new SearchMasterSearchCriteria();
    
                //keywords
                SMKeywords smKeywords = new SMKeywords(); ;
                Dictionary<string, string> dict = new Dictionary<string, string>();
                dict.Add("a5349f533e3aa3ccbc27de2638da38d6", "olympics");
                dict.Add("9cfa7aefcc61936b70aaec6729329eda", "games");
                smKeywords.allString = dict;
    
                //category
                Dictionary<int, string> categorieDict = new Dictionary<int, string>();
                categorieDict.Add(2488, "Olympics 2012 (not participation)");
                categorieDict.Add(8876, "Olympics and culture");
    
                //taxonomies
                Dictionary<string, Dictionary<int, string>> taxonomiesDict = new Dictionary<string, Dictionary<int, string>>();
                taxonomiesDict.Add("Topics", categorieDict);
    
                //metadata
                Dictionary<int, string> metadataDict = new Dictionary<int, string>();
                metadataDict.Add(1, @"private/n");
    
                //clusters
                Dictionary<string, Dictionary<int, string>> clustersDict = new Dictionary<string, Dictionary<int, string>>();
                clustersDict.Add("permission", metadataDict);
    
    
                //dates
                SMDates smDates = new SMDates();
                smDates.startDate = "15-01-2008";
                smDates.endDate = "15-09-2009";
                smDates.useDates = true;
    
                //sort
                SMSort smSort = new SMSort();
                smSort.sortId = 1;
                smSort.sortType = 2;
                smSort.sort = "datetime";
                smSort.sortOrder = "descending";
    
               //add to criteria.
                smCriteria.keywords = smKeywords;
                smCriteria.clusters = clustersDict;
                smCriteria.taxonomies = taxonomiesDict;
                smCriteria.dates = smDates;
                smCriteria.sort = smSort;
    
                //serialize
                string json = JsonConvert.SerializeObject(smCriteria);
                var mydata1 = JsonConvert.DeserializeObject<SearchMasterSearchCriteria>(json);
    

    到那时,两个JSON字符串之间唯一的区别是。anystring、exactstring等的[]和nulls。因此,我将空的方括号替换为卷曲的方括号,它没有错误地进行了偏差化:)

    contentSearchCriteria = contentSearchCriteria.Replace("[]", "{}");
    var mydata = JsonConvert.DeserializeObject<SearchMasterSearchCriteria>(contentSearchCriteria);
    
    4 回复  |  直到 11 年前
        1
  •  9
  •   Timothy Baldridge    16 年前

    老实说,我不会像你那样做的。以下是我检索数据的方法:

    class Data {
         Dictionary<string, Dictionary<string, string>> keywords;
         DatesClass dates;
         .......
    
    }
    
    class DatesClass
    {
        string startDate;
        string endDate;
        bool? useDates
    
    }
    
    
    var mydata = JsonConvert.DeserializeObject<Data>(jsonstring);
    

    我没有填写整个数据类,但你明白了。我发现在输入数据的结构中创建一个对象,然后使用DeserializeObject方法填充数据要容易得多。这也使得代码更加清晰,并且允许编译器检查是否有错别字。

        2
  •  2
  •   Timothy Baldridge    16 年前

    是的,现在的问题在于json.net反序列化对象的方式。在json.net中,C类成为一个json对象。而该类的一个成员将成为一个键,该成员的值将成为该值。

    让我们以分类路径的示例为例。使用上面的类定义json.net,可以查找以下格式的json数据:

    {"taxonomies": {"taxonomies":[{"taxonomy": {"Topics": {1212, "foo"}}}]}
    

    这看起来一点都不像您的输入数据。

    当你创建你的对象时,这样想。

    1)基对象在JSON代码中创建。 2)字典在JSON代码中创建。 3)列表在JSON代码中创建一个[] 4)类的每个成员在JSON代码的中创建一个条目。

    可能有助于调试的是创建结构,填充一些临时数据,然后使用jsonconvert.serialize(myobj)向您展示json认为该结构的样子。

    我认为你的例外来自于上了很多课。

    这可能是您希望代码的taxominies部分看起来像的:

    class SMSearchCriteria
    {
            public SMKeywords keywords { get; set; }
            public SMDates dates { get; set; }
            public SMClusters clusters { get; set; }
            public SMTaxominies taxonomies { get; set; }
            public SMSort sort { get; set; }
    }
    
    class SMTaxominies
    {
        public Dictionary<string, string> Topics;
        public Keywords<string, string> Keywords;
    }
    
        3
  •  1
  •   mythz    16 年前

    首先,我将从一个强类型DTO类开始,最好是一个DataContract,这样您就可以选择将其序列化为您想要的任何格式,即JSON、XML、Protobuf等。

    注意:与大多数其他格式相比,JSON实际上序列化/反序列化非常慢(请参见: serialization benchmarks - json.net是“newtonsoft.json” )如果您使用的是富客户端应用程序而不是Web应用程序,则可能需要选择其他序列化格式。不管最终使用哪种格式,您仍然可以重复使用相同的DTO,例如,上面的代码看起来像:

    [DataContract]
    public class MyDto
    {
      [DataMember]
      public Keywords keywords { get; set; }
    }
    
    [DataContract]
    public class Keywords
    {
      [DataMember]
      public List<string> anyString { get; set; }
    
      [DataMember]
      public Dictionary<string,string> allString { get; set; }
    
      [DataMember]
      public List<string> exactString { get; set; }
    
      [DataMember]
      public List<string> notString { get; set; }
    
      [DataMember]
      public List<string> highlightString { get; set; }
    }
    
    var dto = new MyDto { Keywords = { allString = {{"a5349f533e3aa3ccbc27de2638da38d6", "olympics"}} };
    
    var json = JsonConvert.SerializeObject(dto);
    var fromJson = JsonConvert.DeserializeObject<MyDto>(json);
    

    编辑: 添加链接

    看起来您可能与json.net有问题,在这种情况下,您应该尝试其他json.net序列化程序/反序列化程序。Microsoft提供.NET v3.5中包含的System.Runtime.Serialization.json.DataContractJSonserializer。下面是一些帮助程序类,演示如何 serialize 和 de-serialize 杰森。

    Jayrock 是另一个用于.NET的JSON序列化程序,但它比其他程序慢,我发现它对泛型没有很好的支持。

        4
  •  0
  •   Diego Salas    11 年前

    为什么不使用linq to json?

    例如,将“排序”节点映射到类

    var jsonResult = JObject.Parse(jsonString);
    
    var sortItem = from s in jsonResult["sort"]
    select new MySortObject{
                                SortId = s.Value<int>("sortId")
                            };
    

    http://www.newtonsoft.com/json/help/html/QueryJsonLinq.htm