2014-05-08 61 views
1

我正在使用JSON.NET并且必须反序列化此结构。JSON反序列化“unhandy”字典

"NameValue": [ 
    { 
     "Name": "CONO", 
     "Value": "001" 
    }, 
    { 
     "Name": "DIVI", 
     "Value": " " 
    }, 
    { 
     "Name": "LNCD", 
     "Value": "DE" 
    }, 
    { 
     "Name": "CUNO", 
     "Value": "#AT-VORL " 
    }, 
] 

这是一个较大的对象的一部分,我想反序列化到MyType。我可以有一个属性NameValue,这是一个键入对象的列表MyNameValue,它有两个属性NameValue。但这只是一个字典的怪异表示(名字永远不会重叠),所以我想要一个.NET字典,它会更方便。

如何在我的类上使用属性来实现此目的?

什么样的作品是这样的:

private class JsonResponseRecord 
    { 
     public string RowIndex { get; set; } 

     [JsonProperty(PropertyName = "NameValue")] 
     public List<KeyValuePair<string, string>> Values { get; set; } 
    } 

但它与所有的按键都null而值是否正确填写KeyValuePairs的列表结束。我想他会要求JSON有"Key"而不是"Name"


要明确:我想有一个Dictionary<string, string>类型Values属性一样的:

private class JsonResponseRecord 
    { 
     public string RowIndex { get; set; } 

     [JsonProperty(PropertyName = "NameValue")] 
     public Dictionary<string, string> Values { get; set; } 
    } 
+0

我想可能期望的“钥匙”,而不是“名”,但是这必须是相当容易,虽然克服了,最坏的情况下,你可以使用动态类型,以填补KeyValuePair或将它反序列化为一个具有正确名称的类,也可能是一个选项。 – Viezevingertjes

回答

1

我能用自定义转换器做到这一点。如果这可能与JSON.NET标准,我将不胜感激输入。

这才是我的接收对象:

internal class ResponseRecord 
{ 
    public string RowIndex { get; set; } 

    [JsonProperty(PropertyName = "NameValue"), JsonConverter(typeof(JsonNameValueListToDictionaryConverter))] 
    public Dictionary<string, string> Values { get; set; } 
} 

这是转换器代码:

/// <summary> 
/// Converts the NameValue-array with object containing name and value to a Dictionary. 
/// </summary> 
internal class JsonNameValueListToDictionaryConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotSupportedException(); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     Dictionary<string, string> dictionary = existingValue as Dictionary<string, string> ?? new Dictionary<string, string>(); 

     if (reader.TokenType == JsonToken.StartArray) 
     { 
      int startDepth = reader.Depth; 
      while (reader.Read()) 
      { 
       if ((reader.Depth == startDepth) && (reader.TokenType == JsonToken.EndArray)) break; 

       if (reader.TokenType == JsonToken.StartObject) 
       { 
        KeyValuePair<string, string> kvp = GetKeyValueFromJsonObject(reader, "Name", "Value"); 
        dictionary[kvp.Key] = kvp.Value; // always override existing keys 
       } 
       else 
       { 
        throw new NotSupportedException(String.Format("Unexpected JSON token '{0}' while reading special Dictionary", reader.TokenType)); 
       } 
      } 
     } 

     return dictionary; 
    } 

    private KeyValuePair<string, string> GetKeyValueFromJsonObject(JsonReader reader, string propNameKey, string propNameValue) 
    { 
     string key = null; 
     string value = null; 
     int startDepth = reader.Depth; 
     while (reader.Read()) 
     { 
      if ((reader.TokenType == JsonToken.EndObject) && (reader.Depth == startDepth)) break; 

      if (reader.TokenType == JsonToken.PropertyName) 
      { 
       string propName = reader.Value as string; 
       if (propName == null) continue; 
       if (propName.Equals(propNameKey, StringComparison.InvariantCulture)) 
       { 
        key = reader.ReadAsString(); 
       } 
       else if (propName.Equals(propNameValue, StringComparison.InvariantCulture)) 
       { 
        value = reader.ReadAsString(); 
       } 
      } 
     } 
     return new KeyValuePair<string, string>(key, value); 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return (objectType.Equals(typeof(Dictionary<string, string>))); 
    } 

} 
1

使用JSON.NET,选择性粘贴 “作为JSON类”,它给你: -

public class Rootobject 
{ 
public Namevalue[] NameValue { get; set; } 
} 

public class Namevalue 
{ 
public string Name { get; set; } 
public string Value { get; set; } 
} 
+0

是的,但这意味着我将通过循环访问数组并将“Name”与“DIVI”进行比较,并在发现时使用“Value”来访问密钥“DIVI”。当读到字典时,这是相当容易和快速的。 – ZoolWay

2

首先一点校正,您张贴的JSON字符串。它应该是这样的:

var json = { 
     "NameValue": [ 
     { 
      "Name": "CONO", 
      "Value": "001" 
     }, 
     { 
      "Name": "DIVI", 
      "Value": " " 
     }, 
     { 
      "Name": "LNCD", 
      "Value": "DE" 
     }, 
     { 
      "Name": "CUNO", 
      "Value": "#AT-VORL " 
     } 
     ] 
    } 

可以acchieve你想要使用JSON.NET内置Linq to JSON。这里是samlple代码:

var jObject = JObject.Parse(json); 
    var jsonResponseRecordObj = new JsonResponseRecord 
       { 
        Values = 
         jObject["NameValue"].ToDictionary(row => (string) row["Name"], row => (string) row["Value"]) 
       };