假设我们有以下代码:
Type t = typeof(UInt64);
var def = Activator.CreateInstance(t);
Console.WriteLine(def.GetType());
string json = "18446744073709551615";
object parsedObject = JsonConvert.DeserializeAnonymousType(json, def);
Console.WriteLine(parsedObject.GetType());
输出为:
System.UInt64
System.Numerics.BigInteger
由于我明确地向DeserializeAnonymousType
提供了def
,其类型为UInt64
,因此我也希望UInt64
作为输出,尤其是因为18446744073709551615是有效的{{ 1}}值(允许的最大值,但是我也检查了18446744073709551614,它是相同的。)
为什么会这样?我检查了Newtonsoft Github的问题,却一无所获(至少在未解决的问题中没有)。
如何强制使用我事先知道的正确类型(动态地,我只有UInt64
)?显然,如果仅发生在System.Type
上,我可以进行检查并明确进行转换。
答案 0 :(得分:2)
您的问题是JsonConvert.DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
并没有达到您的期望。它不会将JSON字符串反序列化为T anonymousTypeObject
参数的实际类型。它将JSON字符串反序列化为参数的 声明类型 -在您的情况下为 object
。
这可以从reference source中看到:
public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
{
return DeserializeObject<T>(value);
}
T anonymousTypeObject
从未真正使用过。而是在调用DeserializeAnonymousType
时完全通过类型推断来指定目标类型-特别是从代码中变量def
的声明类型中进行指定。但是def
被隐式声明为object
,因为这是Activator.CreateInstance(Type type)
声明要返回的内容。因此object
就是Json.NET将JSON反序列化为-某种.Net类型足以捕获传入的JSON。由于BigInteger
足以捕获传入的JSON,因此Newtonsoft会选择该类型而不是Uint64
。
如果要强制Json.NET反序列化为特定对象的实际,具体类型,请使用JsonConvert.DeserializeObject(string value,Type type)
:
object parsedObject = JsonConvert.DeserializeObject(json, def.GetType());
演示小提琴here。