Json.net DeserializeAnonymousType returns BigInteger 而不是 UInt64

Json.net DeserializeAnonymousType returns BigInteger instead of UInt64

假设我们有以下代码:

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

因为我明确地用 def 喂养 DeserializeAnonymousType,其类型是 UInt64,我希望 UInt64 也作为输出,特别是因为 18446744073709551615 是有效的UInt64 值(最大值,当然,但我也检查了 18446744073709551614,它是一样的)。

为什么会这样?我检查了 Newtonsoft Github issues,但什么也没发现(至少,未解决的 issues)。

如何强制我预先知道的正确类型(动态地,我只有 System.Type)?显然,如果它只发生在 UInt64 时,我可以进行检查并显式转换。

您的问题是 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) 被声明为 return 的内容。因此 object 是 Json.NET 将 JSON 反序列化为——某种足以捕获传入 JSON 的 .Net 类型。由于 BigInteger 足以捕获传入的 JSON,Newtonsoft 恰好选择了该类型而不是 Uint64

如果你想强制Json.NET反序列化为特定对象的实际具体类型,请使用JsonConvert.DeserializeObject(string value,Type type):

object parsedObject = JsonConvert.DeserializeObject(json, def.GetType());

演示 fiddle here.

我使用了这个例子并认为我会把它推进到 classes:

的列表
List<_class> listOfClasses = new List<_class>();
var content = response.Content.ReadAsStringAsync().Result;

object parsedObject = JsonConvert.DeserializeAnonymousType(content, Activator.CreateInstance(typeof(_class)));
                        
var _listOfClasses = JsonConvert.DeserializeObject<List<_class>>(parsedObject.ToString());

listOfClasses = _listOfClasses;

这样做是从 API 中使用 TEntity 的列表,然后将其解析回与消费者

匹配的 class