我从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&lt; int&gt; ?我看到它有关于它的元数据,因为$ type和$ values属性在动态对象的Result视图中可见。
感谢任何帮助,谢谢。
为帮助隔离问题并回答评论问题,我创建了一个测试应用。事实证明,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)
}
}
}
答案 0 :(得分:1)
我在这里没有看到错误。问题是,即使您指定反序列化的对象类型应为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()
的重载而不用类型,并传递相同的{用于序列化的{1}}:
JsonSerializationSettings