2017-02-24 66 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。如果您想要利用动态语言运行时,那么使用最流行的语法即可。 –