2017-05-04 112 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