2014-04-07 23 views
1

很可能我沒有經歷過足夠的東西,我的問題有點愚蠢: 爲了學習的目的,我試圖連接到一個REST服務,它提供了JSON數據。帶有動態根對象的JSON

從我所瞭解的情況來看,JSON的目的是將相同的數據傳遞給任何可能的客戶端,而無需擁有自己的狀態。

我的代碼看起來像這樣:

public static void DoSomething() 
    { 
     HttpClient client = new HttpClient(); 

     client.BaseAddress = new Uri("SomeUrl")); 

     // Add an Accept header for JSON format. 
     client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 

     // List data response. 
     HttpResponseMessage response = client.GetAsync("").Result; 

     if (response.IsSuccessStatusCode) 
     { 
      Task<Stream> readTask = response.Content.ReadAsStreamAsync(); 
      readTask.ContinueWith(task => 
      { 
       DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(RootObject)); 
       using (Stream result = task.Result) 
       { 
        result.Position = 0; 
        RootObject obj = (RootObject)ser.ReadObject(result); 
       } 
      }); 
     } 
     else 
     { 
      Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase); 
     } 

    } 


    public class Sum 
    { 
     public int id { get; set; } 
     public string name { get; set; } 
     public int profileIconId { get; set; } 
     public int summonerLevel { get; set; } 
     public long revisionDate { get; set; } 
    } 

    public class RootObject 
    { 
     public Sum khalgor { get; set; } 
    } 

但這裏是我的問題:我創建了這個類的「點心」和「RootObject」通過使用本網站http://json2csharp.com/時,JSON字符串是這樣看:

{"khalgor":{"id":23801741,"name":"Khalgor","profileIconId":7,"summonerLevel":30,"revisionDate":1396876104000}} 

問題:名稱「Khalgor」似乎被用作根對象,但它是一個名稱。所以如果我想用另一個名字,我不得不使用另一個RootObject。

創建這樣的結構沒有多大意義,所以我的問題是:這裏最好的做法是什麼?我是否將此RootObject/Property手動映射到另一個對象?我是否使用一些反射來動態創建一個屬性或重命名它?

像往常一樣,非常感謝所有響應

馬蒂亞斯

編輯:

我修修補補角落找尋了一下,這是我的一個解決方案的第一個想法:

public static class LOLObjectFactory 
{ 
    public static ILOLObject Create(string jsonString) 
    { 
     JavaScriptSerializer jss = new JavaScriptSerializer(); 
     Dictionary<String, object> entry = (jss.Deserialize<dynamic>(jsonString) as Dictionary<string, object>).First().Value as Dictionary<String, object>; 

     Type selectedType = null; 

     List<string> fieldNames = entry.Select(f => f.Key).OrderBy(f => f).ToList(); 

     Type[] types = typeof(ILOLObject).Assembly.GetTypes(); 
     foreach(var type in types) 
     { 
      List<string> typeProperties = type.GetProperties().Select(f => f.Name).OrderBy(f => f).ToList(); 

      if (fieldNames.SequenceEqual(typeProperties) && typeof(ILOLObject).IsAssignableFrom(type)) 
      { 
       selectedType = type; 
       break; 
      } 
     } 

     ILOLObject result = System.Activator.CreateInstance(selectedType) as ILOLObject; 
     foreach(var prop in result.GetType().GetProperties()) 
     { 
      prop.SetValue(result, entry.First(f => f.Key == prop.Name).Value); 
     } 

     return result; 
    } 
} 

所以我擁有的所有對象都實現了ILOLObject。我確定它不適用於任何事情,但我想這會是一個好方法?編輯2:只要看看它,我就會看到很多工作要做,但我認爲它背後的想法很清楚。

+0

Json的目的是爲了傳輸目的將數據包裝到字符串表示中。您提到的無狀態適用於REST。 – BlueM

回答

1

如果您想完全忽略根目錄(例如每次更改其名稱),請使用Json.NET將其解析爲對象並忽略最上面的元素。例如:

JObject obj = JObject.Parse(json); 
if (obj != null) 
{ 
    var root = obj.First; 
    if (root != null) 
    { 
     var sumJson = root.First; 
     if (sumJson != null) 
     { 
      var sum = sumJson.ToObject<Sum>(); 
     } 
    } 
} 
+0

你確定嗎?我換成 public sum testProp {get;組; } 現在它總是空。看起來它確實需要「khalgor」。我可以使用類似DataMember屬性的東西嗎? 我真的很喜歡沒有RootObject,因爲我只是想要在「khalgor」屬性中的數據。 –

+0

如果你解析Json到你的對象中,並且根在Json文本中沒有命名爲testProp,那麼當然它不會被映射到你的對象。所以你的問題基本上是如何忽略根? – BlueM

+0

@MatthiasMüller查看我的更新回答。我認爲這就是你想要的。它將忽略根元素的名稱並提取它的一個嵌套和元素。 – BlueM

2

我認爲最好的方法對JSON「碎片」是反序列化到一個動態對象:

dynamic stuff = JsonConvert.DeserializeObject(inputData); 

然後你就可以反序列化部件,使感覺入適當的.NET對象。

SomeObject o = JsonConvert.DeserializeObject<SomeObject>(stuff["someProperty"].ToString()); 
+0

謝謝,所以沒有簡單的方法可以這樣說:「將RootObject和Screw屬性」khalgor「擰緊,然後將數據提交給我!」 ? –