2017-02-24 103 views
2

大多數情況下,默認情況下,我們沒有在我們選擇的靜態語言中定義類,這爲我們解釋瞭如何對其進行反序列化提供了一個尷尬的問題。 JSON從一個調用返回到公開和公開的文本API,專用於單一語言,除了例如HTML和JSON。如何從Web api JSON響應中派生C#動態對象?

在.NET中,這些天來,幾乎所有的API查詢與HttpClient完成的,像下面的谷歌圖書API ISBN查詢:

public class GoogleBooksClient 
{ 
    private const string IsbnUrl = "books/v1/volumes?q=isbn:{0}"; 
    private static HttpClient _client = new HttpClient(); 
    ... 
    public async Task<object> GetDetailsByIsbn(string isbn) 
    { 
     var json = await _client.GetStringAsync(string.Format(IsbnUrl, isbn)); 
     dynamic objX = JsonConvert.DeserializeObject(json); 
     return objX; 
    } 
} 

這裏最大的問題是,是否objX聲明var」, objectdynamic,當DeserializeObject在沒有已知類型的情況下調用時,它總是引用一個大的,醜陋的JObject實例。在這種情況下,返回的JSON對象非常複雜,並且有些龍在等待那些試圖編寫可以解析JSON的C#類的人。

這是一個理想的和有意使用C#dynamic對象的機會,在解析JSON的同時,屬性(以及API響應的很少函數)可遞歸添加到所述動態對象中。

相反,NewtonSoft.JSON將JSON保存的數據與相當不透明的Jobject數據結構的繁重的繁文lig節連接緊緊地綁定在一起。我很驚訝,也很失望,到目前爲止,牛頓軟件公司不能簡單地提取一個純粹的動態對象,沒有迷宮的所有混亂的官僚作風。

是否有其他方法可以簡單地將JSON解析爲C#動態對象,就像在其他場景中將其解析爲顯式動態JavaScript對象一樣?

新增:通過 「混淆他們JObject的官僚迷宮」,我指的是下面的代碼:

var json = JsonConvert.SerializeObject(new Person {Id = 196912135012878, Age = 47, Name = "Brady"}); 
var jObj = JsonConvert.DeserializeObject(json); 

產生JObject例如,我的調試器顯示爲:

Debugger view of JObject properties

對我來說,這看起來更像是在解析JSON時應該在內部使用的東西, nd不是該解析的最終產品,它應該只是從該JSON解析的屬性的純粹表示。理想情況下,這是一個C#動態對象,沒有屬性可供任何解析器使用。

+1

http://www.newtonsoft.com/json/help/html/QueryJsonDynamic.htm – dman2306

+1

對於'JObject'類型的標記(而不是''JArray''),你可以反序列化爲'ExpandoObject'。請參閱http://www.newtonsoft.com/json/help/html/SerializationGuide.htm#Dynamic。不確定你的問題是什麼。你是什​​麼意思*迷惑他們JObject迷宮*的官僚作風? – dbc

+1

@dbc增加了我不喜歡'JObject'的原因。感謝「ExpandoObject」提示。這確實會有所幫助。 – ProfK

回答

3

而不是JObject,您可以反序列化爲由Json.NET的內置轉換器ExpandoObjectConverter支持的ExpandoObject。如果是數組,則可以反序列化爲List<ExpandoObject>,然後選擇List<dynamic>。如果是原始值,則可以返回JValue.Value

舉例來說,如果你事先知道你的JSON表示一個對象,只是做:

dynamic dyn = JsonConvert.DeserializeObject<ExpandoObject>(json); 

如果你事先不知道哪根JSON容器可能是,你可以加載它作爲一個JToken和使用下面的擴展方法:

public static class JsonExtensions 
{ 
    public static dynamic ToDynamic(this JToken token) 
    { 
     if (token == null) 
      return null; 
     else if (token is JObject) 
      return token.ToObject<ExpandoObject>(); 
     else if (token is JArray) 
      return token.ToObject<List<ExpandoObject>>().Cast<dynamic>().ToList(); 
     else if (token is JValue) 
      return ((JValue)token).Value; 
     else 
      // JConstructor, JRaw 
      throw new JsonSerializationException(string.Format("Token type not implemented: {0}", token)); 
    } 
} 

然後做:

dynamic dyn = JsonConvert.DeserializeObject<JToken>(json).ToDynamic(); 

樣品fiddle

+1

ExpandoObjectConverter是要走的路,IMO。如果您想要利用動態語言運行時,那麼使用最流行的語法即可。 –