使用RestSharp将具有未知键的字典反序列化

时间:2017-05-04 20:44:32

标签: c# restsharp json-deserialization

我目前正在获取一个形状类似于以下形状的JSON对象:

{
 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将其反序列化为一个对象,其中Item1,Item2和其余部分填入一个Dictionary我目前有以下代码:

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

我希望将Item1,Item2等作为Dictionary的键和下面的值来填充Data类作为Dictionary的值。但它现在还没有工作(我的结构的其余部分是,它只是这个最里面的部分)。我只是接近结构错了吗?我想避免为Item1和Item2创建一个特定的类。

2 个答案:

答案 0 :(得分:1)

<强>步骤: 1。始终以合理的方式塑造JSON对象

如果以更合理的方式重构json对象,这个问题会更容易处理。现在,您有n个与“value”处于同一级别的数据对象,并且您正在动态更改其属性名称。

就个人而言,我会重塑json:

Op

第2步:将Newtonsoft.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
            }
         ]
      }
   ]
}

第3步:反序列化

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

答案 1 :(得分: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);
    }
}