我从 Json.net 的版本 5 更新到版本 6.0.8。但是,我的代码停止工作了,我花了一段时间才明白,在以前的版本中,它能够处理用列表实例化泛型类型的情况。但现在,它没有。我的问题是,是否需要调整任何设置才能获得旧行为?
在老图书馆,上课
public class Result<T>
{
public T Data
{
get;
set;
}
public int ResultCode
{
get;
set;
}
}
适用于用类似的东西实例化类的情况
Result<List<int>> result;
所以在我的代码中我做了类似的事情
dynamic result = JsonConvert.DeserializeObject(result, typeof(JObject));
int firstValue = (int)result.Data[0];
但是,对于最新的 Json.Net,它会失败并抛出异常(使用无效键值访问的 JObject 值:0。预期对象属性名称。)。我发现的唯一解决办法是
var resultList = result.Data.ToObject<List<int>>();
int firstValue = resultList[0];
显然,这种破坏动态的目的,我宁愿回到旧的行为。我能做些什么来告诉 Json.net T 可以是 List
感谢任何帮助,谢谢。
为了帮助隔离问题并回答评论问题,我创建了一个测试应用程序。事实证明,TypeNameHandling.All 选项是导致参数异常的原因。我在代码中添加了注释以显示好/坏的序列化。是的,我认为我们的代码中需要 All 选项。
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ShowingBug
{
public class InterestingResult
{
public string Information { get; set; }
}
public class Result<T>
{
public T Data { get; set; }
public int ResultCode { get; set; }
}
class Program
{
static void Main(string[] args)
{
var veryInteresting = new List<InterestingResult>();
veryInteresting.Add(new InterestingResult() { Information = "Good" });
Result<List<InterestingResult>> operationResult = new Result<List<InterestingResult>>();
operationResult.Data = veryInteresting;
operationResult.ResultCode = 1;
JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
};
var json = JsonConvert.SerializeObject(operationResult, serializerSettings);
dynamic result = JObject.Parse(json);
string information = (string)result.Data[0].Information;
Console.Out.WriteLine(information);
//The above works, however after some digging...
// I found that the option we use is not Auto, but All
serializerSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
json = JsonConvert.SerializeObject(operationResult, serializerSettings);
result = JObject.Parse(json);
// Now, you get an ArgumentException from Json.net 6.0.8 on the following line
information = (string)result.Data[0].Information;
// It worked in previous version of Json.Net
// I'm using .net 4.5.2 (if that makes a difference)
}
}
}
最佳答案
我在这里没有看到错误。问题是你似乎期待得到你原来的 Result<T>
即使您指定反序列化对象类型应为 JObject
,也返回对象.这永远行不通,因为 Result<T>
不是 JObject
, 和一个 JObject
不能保存像 Result<T>
这样的自定义对象. JObject
只能容纳 JProperty
的集合对象,那些只能保存从 JToken
派生的值.这是设计使然。
当您调用 JsonConvert.DeserializeObject(json, typeof(JObject))
时,强制返回对象为 JObject
, 即使接收变量声明为 dynamic
.同样,JObject.Parse()
将始终返回 JObject
.
如果您想取回原始对象,尊重 JSON 中的嵌入式类型信息,您应该使用 JsonConvert.DeserializeObject()
的重载没有类型,传递相同的 JsonSerializationSettings
你用来序列化的:
JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
dynamic result = JsonConvert.DeserializeObject(json, serializerSettings);
关于json.net - 为什么 Json.Net 6 不能将 T 反序列化为动态对象中的泛型列表? (适用于版本 5),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30735129/