2017-05-04 51 views
2

我目前得到一个JSON对象类似以下的形状未知键:反序列化词典与RestSharp

{ 
more data here... 
    "years": { 
    "value": 2013, 
    "item1": { 
     "total": 0.1044, 
     "Low": 0.0143, 
     "Mid": 0.1044, 
     "High": 0.3524, 
     "min": 0.0143, 
     "max": 0.3524, 
    }, 
    "item2": { 
     "total": 0.1702, 
     "Low": 0.167, 
     "Mid": 0.1702, 
     "High": 0.1737, 
     "min": 0.167, 
     "max": 0.1737, 
    },... 
    } 
} 

我遗憾的是,有超过JSON的形状没有控制。

我试图让RestSharp反序列化到一个对象,其中项目1,项目2本,其余补入字典目前,我有以下代码:

public class Year 
{ 
    public int Value { get; set; } 
    public Dictionary<string, Data> Data { get; set; } 
} 

public class Data 
{ 
    public decimal Total { get; set; } 
    public decimal Low { get; set; } 
    public decimal Mid { get; set; } 
    public decimal High { get; set; } 
    public decimal Min { get; set; } 
    public decimal Max { get; set; } 
} 

而且我希望能得到项目1, Item2等作为Dictionary的键和下面的值来填充Data类作为Dictionary的值。但目前它不工作(我的结构的其余部分是,它只是这个最内部的部分)。我刚刚接近错误的结构?我想避免必须为Item1和Item2创建特定的类。

回答

1

您可以使用自定义JsonConverter

public class YearConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(Year); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var obj = JObject.Load(reader); 

     int year = (int)obj["value"]; 
     var data = new Dictionary<string, Data>(); 

     foreach (var dataItem in obj.Children() 
      .OfType<JProperty>() 
      .Where(p => p.Name.StartsWith("item"))) 
     { 
      data.Add(dataItem.Name, dataItem.Value.ToObject<Data>()); 
     } 

     return new Year 
     { 
      Value = year, 
      Data = data 
     }; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

装饰你的Year类与转换器:

[JsonConverter(typeof(YearConverter))] 
public class Year 
{ 
    public int Value { get; set; } 
    public Dictionary<string, Data> Data { get; set; } 
} 

使用它像这样,例如:

class Program 
{ 
    static void Main(string[] args) 
    { 
     string json = @" 
{ 
    ""value"": 2013, 
    ""item1"": { 
    ""total"": 0.1044, 
    ""Low"": 0.0143, 
    ""Mid"": 0.1044, 
    ""High"": 0.3524, 
    ""min"": 0.0143, 
    ""max"": 0.3524, 
    }, 
    ""item2"": { 
    ""total"": 0.1702, 
    ""Low"": 0.167, 
    ""Mid"": 0.1702, 
    ""High"": 0.1737, 
    ""min"": 0.167, 
    ""max"": 0.1737, 
    } 
}"; 
     var years = JsonConvert.DeserializeObject<Year>(json); 
    } 
} 
1

步骤: 1.始终塑造你的JSON对象以逻辑方式

,如果你在一个更合乎逻辑的方式调整了您的JSON对象,这个问题将是显著好办了。现在,您有n个数据对象处于与“值”相同的级别,并且您正在动态更改其属性名称。

就个人而言,我会重塑JSON这样:

{ 
    "years":[ 
     { 
     "value":2013, 
     "data":[ 
      { 
       "name":"item1", 
       "total":0.1044, 
       "Low":0.0143, 
       "Mid":0.1044, 
       "High":0.3524, 
       "min":0.0143, 
       "max":0.3524 
      }, 
      { 
       "name":"item2", 
       "total":0.1702, 
       "Low":0.167, 
       "Mid":0.1702, 
       "High":0.1737, 
       "min":0.167, 
       "max":0.1737 
      } 
     ] 
     } 
    ] 
} 

第2步:添加Newtonsoft.Json属性到类

这可以很容易地反序列化

public class Base 
{ 
    [JsonProperty("years")] 
    public List<Year> years { get; set; } 
} 

    public class Year 
    { 
     [JsonProperty("value")] 
     public int Value { get; set; } 

     [JsonProperty("data")] 
     public List<Data> data { get; set; } 
    } 

    public class Data 
{ 
     [JsonProperty("name")] 
    public string name { get; set; } 
     [JsonProperty("total")] 
     public decimal Total { get; set; } 
     [JsonProperty("Low")] 
     public decimal Low { get; set; } 
     [JsonProperty("Mid")] 
     public decimal Mid { get; set; } 
     [JsonProperty("High")] 
     public decimal High { get; set; } 
     [JsonProperty("min")] 
     public decimal Min { get; set; } 
     [JsonProperty("max")] 
     public decimal Max { get; set; } 
    } 

第3步:反序列化它

Base myYears = JsonConvert.DeserializeObject<Base>(myJsonString); 
+0

谢谢为您的输入。我可能应该提到我无法控制JSON格式,我会编辑它。我试图避免必须引入另一个库,但我会记住JSON.Net。 –

+0

您可以将传入的JSON映射到您想要的外观,以便您轻松重构 – Chris

+0

我强调重构它,因为我认为该模型实际上在逻辑上已损坏。在“年”之下,你有一堆属性,未知名称,其中一个将是一个字符串,其余的将是Data对象。我们不知道名称会是什么,因此我们无法知道什么C#变量名甚至绑定到。另一种方法是使用这个:http://www.newtonsoft.com/json/help/html/DeserializeCustomCreationConverter.htm你可以编写自定义规则并覆盖任务,使其看起来如何,我想。 – Chris