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

C# 使用RestSharp反序列化具有未知键的字典,c#,restsharp,json-deserialization,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": { "

我目前得到一个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和rest填充到一个字典中,我目前有以下代码:

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; }
}
公共课程年
{
公共int值{get;set;}
公共字典数据{get;set;}
}
公共类数据
{
公共十进制总数{get;set;}
公共十进制低位{get;set;}
公共十进制中间值{get;set;}
公共十进制高位{get;set;}
公共十进制最小值{get;set;}
公共十进制最大值{get;set;}
}
我希望将Item1、Item2等作为字典的键,并将下面的值作为字典的值填充到数据类中。但它目前不起作用(我的结构的其余部分是,它只是最里面的部分)。我只是走错路了吗?我希望避免为Item1和Item2创建特定的类。

步骤: 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; }
    }
公共类基
{
[JsonProperty(“年”)]
公共列表年份{get;set;}
}
公课年
{
[JsonProperty(“价值”)]
公共int值{get;set;}
[JsonProperty(“数据”)]
公共列表数据{get;set;}
}
公共类数据
{
[JsonProperty(“名称”)]
公共字符串名称{get;set;}
[JsonProperty(“总计”)]
公共十进制总数{get;set;}
[JsonProperty(“低”)]
公共十进制低位{get;set;}
[JsonProperty(“Mid”)]
公共十进制中间值{get;set;}
[JsonProperty(“高”)]
公共十进制高位{get;set;}
[JsonProperty(“min”)]
公共十进制最小值{get;set;}
[JsonProperty(“max”)]
公共十进制最大值{get;set;}
}
步骤3:反序列化它

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

您可以使用自定义的
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();
    }
}
像这样使用它,例如:

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);
    }
}
类程序
{
静态void Main(字符串[]参数)
{
字符串json=@”
{
“价值”:2013年,
“第1项”:{
“总计”:0.1044,
“低”:0.0143,
“中期”:0.1044,
“高”:0.3524,
“min”:0.0143,
“最大值”:0.3524,
},
“项目2”:{
“总计”:0.1702,
“低”:0.167,
“中期”:0.1702,
“高”:0.1737,
“min”:0.167,
“最大值”:0.1737,
}
}";
var years=JsonConvert.DeserializeObject(json);
}
}

感谢您的输入。我可能应该提到我对JSON格式没有控制权,我将在中编辑它。我试图避免引入另一个库,但我会记住JSON.Net。你可以将传入的JSON映射为你想要的样子,这样你就可以轻松地重新构造。我强调重新构造它,因为我认为模型实际上在逻辑上是不完整的。在“years”下面,有一堆属性、未知名称,其中一个是字符串,其余的是数据对象。我们不知道这些名称将是什么,因此我们甚至不知道将其绑定到什么C#变量名。另一种选择是使用这种方法:你可以编写自定义规则并覆盖赋值,使它看起来像你想要的那样,我想知道我如何在不反序列化的情况下重新映射JSON。您是否建议在使用之前操作JSON字符串以使其更易于解析?我发布的链接展示了如何为Json对象方法编写自定义规则,您可以覆盖常规的getter和setter,因此理论上,您应该能够将其与JsonProperty属性结合起来进行完全序列化。这是我希望您使用JavaScript而不是.NET的时候之一!
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);
    }
}