2010-02-15 35 views
7

我试图在Windows窗体中使用JSON.NET框架从JSON字符串中读取一些信息。但是我努力获得来自“taxonomies->主题”阵列的字典和“集群”JSON.NET到C#对象

{ 
    "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"]; 

UPDATE:

至于建议我加入

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); 

那时候2个json字符串之间的唯一区别在哪里。 []和对anyString,exactString等空值,因此我更换了空方括号卷发的人,并没有错误:)

contentSearchCriteria = contentSearchCriteria.Replace("[]", "{}"); 
var mydata = JsonConvert.DeserializeObject<SearchMasterSearchCriteria>(contentSearchCriteria); 

回答

9

老实跟你,我不会做他们的方式desearialized你正在做这件事。以下是关于检索数据的方式:

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方法填充数据要容易得多。这也使得代码更清晰,并允许编译器检查拼写错误。

+0

蒂莫西嗨,你建议我已经更新了类的问题。但我得到一个例外。 –

1

我会用一个强类型的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 /解-serializers。微软发布了一个系统。包含在.NET v3.5中的Runtime.Serialization.Json.DataContractJsonSerializer。以下是一些帮助类,向您展示如何serializede-serialize JSON。

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

+0

我从系统中收到JSON没有控制权。我已经用新类更新了这个问题,但我得到了一个异常。 –

+0

ok,那么你可能可以制作一个松散类型的DTO模型,只需要Dictionary 和List 的属性? – mythz

+0

你能举个例子吗? json.net如何知道要映射到哪些属性? –

2

是的,你的问题现在是JSON.net反序列化对象的方式。在JSON.net中,C#类成为Json对象。并且该类别的成员将成为一个Key,其成员的价值将成为价值。

让我们以分类标准路径的例子为例。使用您的上述类定义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; 
} 
0

你为什么不使用LINQ到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