在Json.NET文档中的performance tips的帮助下,我整理了一个从远程资源下载/反序列化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);
}
}
}
}
我想要一个返回dynamic
的非通用版本。使用GetJsonAsync<dynamic>(url)
调用上述方法有效,直到您尝试访问结果的动态属性,此时我得到:
'Newtonsoft.Json.Linq.JObject' does not contain a definition for '[MyProperty]'
我从字符串中看到过how to deserialize to a dynamic,但是还没有看到直接从流中执行此操作的示例,这样做会更好,因为它的内存效率更高。这可能吗?
答案 0 :(得分:4)
事实证明,这与Json.NET几乎没有关系,而是与我对动态的理解有关(我很少使用)。感谢@Peter Richie,我发现如果我将MyProperty明确地转换为字符串,GetJsonAsync<dynamic>
确实有效。但我宁愿不必那样做。使用我的原始方法和real working endpoint,这里有3个场景;只有最后一个有效:
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!
有了这些知识,我原始方法的非泛型重载看起来像这样:
public async Task<dynamic> GetJsonAsync(string url) {
dynamic d = await GetJsonAsync<ExpandoObject>(url);
return d;
}
用户可以这样做:
var x = await GetJsonAsync(url);
Assert.AreEqual("MyValue", x.MyProperty); // pass!
答案 1 :(得分:2)
听起来有些信息没有提供。以下工作对我来说很好:
private T ReadJson<T>(Stream stream)
{
using (var reader = new StreamReader(stream))
{
using (var jr = new JsonTextReader(reader))
{
dynamic d = new JsonSerializer().Deserialize(jr);
return d;
}
}
}
//...
var d = ReadJson<dynamic>(new MemoryStream(Encoding.UTF8.GetBytes("{'MyProperty' : 'MyValue'}")));
Debug.WriteLine((String)d.MyProperty);