Json.NET - 直接从流反序列化为动态?

Tod*_*ier 6 .net c# json stream json.net

在Json.NET文档中的性能提示的帮助下,我整理了一个从远程资源下载/反序列化JSON的方法:

public async Task<T> GetJsonAsync<T>(string url) 
{
  using (var stream = await new HttpClient().GetStreamAsync(url))
  {
    using (var sr = new StreamReader(stream))
    {
      using (var jr = new JsonTextReader(sr))
      {
        return new JsonSerializer().Deserialize<T>(jr);
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我想要一个返回a的非泛型版本dynamic.用work调用上面的方法GetJsonAsync<dynamic>(url),直到你尝试访问结果的动态属性,此时我得到:

'Newtonsoft.Json.Linq.JObject' does not contain a definition for '[MyProperty]'
Run Code Online (Sandbox Code Playgroud)

我已经看到如何从字符串反序列化为动态,但没有看到直接从流中执行它的工作示例,这将是更好的,因为它更有内存效率.这可能吗?

Tod*_*ier 6

It turns out this had little to do with Json.NET and more to do with my understanding of dynamics (which I rarely use). Thanks to @Peter Richie, I found that GetJsonAsync<dynamic> does work if I explicitly cast MyProperty to a string. But I'd rather not have to do that. Using my original method and a real working endpoint, here are 3 scenarios; only the last one works:

var url = "http://echo.jsontest.com/MyProperty/MyValue"; // great testing site!

var x1 = await GetJsonAsync<dynamic>(url);
Assert.AreEqual("MyValue", x1.MyProperty); // fail!

dynamic x2 = await GetJsonAsync<dynamic>(url);
Assert.AreEqual("MyValue", x2.MyProperty); // fail!

dynamic x3 = await GetJsonAsync<ExpandoObject>(url);
Assert.AreEqual("MyValue", x3.MyProperty); // pass!
Run Code Online (Sandbox Code Playgroud)

有了这些知识,我的原始方法的非泛型重载如下所示:

public async Task<dynamic> GetJsonAsync(string url) {
    dynamic d = await GetJsonAsync<ExpandoObject>(url);
    return d;
}
Run Code Online (Sandbox Code Playgroud)

用户可以这样做:

var x = await GetJsonAsync(url);
Assert.AreEqual("MyValue", x.MyProperty); // pass!
Run Code Online (Sandbox Code Playgroud)