【问题标题】:Json.net DeserializeAnonymousType returns BigInteger instead of UInt64Json.net DeserializeAnonymousType 返回 BigInteger 而不是 UInt64
【发布时间】:2019-05-04 14:28:25
【问题描述】:

假设我们有以下代码:

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

由于我明确地将DeserializeAnonymousTypedef 一起输入,其中的类型是UInt64,我也希望UInt64 作为输出,特别是因为18446744073709551615 是一个有效的UInt64 值(最大值,已授予,但我也检查了 18446744073709551614,它是一样的)。

为什么会这样?我检查了 Newtonsoft Github 问题,但一无所获(至少在未解决的问题中没有)。

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

【问题讨论】:

  • 看看这个thread是否有帮助。
  • @CodingYoshi 谢谢!它有帮助,但线程指出 json 数值是“IEEE 双精度浮点数”。这意味着即使 Int64.MaxValue 也不行,但它是!
  • 如果您需要特定的类型处理,通常会提供特定的转换器,您可以在其中测试转换为类似以下内容的类型:public override bool CanConvert(Type t) => t == typeof(ulong);。但是,由于18446744073709551615 == ulong.MaxValue,下一个安全类型是BigInteger(你永远不知道下一个值是否可以是18446744073709551616
  • @Jimi 然后你在哪里定义它是“安全”的限制?然后我们就可以将所有内容都表示为 BigInteger。正如我所说,对于 18446744073709551614 也是如此。同样在 C# 本身中,如果您编写 var x = 18446744073709551615,它将产生类型为 ulong 的 x。由于 netwonsoft json 是 C# 库,我希望行为一致。
  • 顺便说一句,如果您不想提供自定义转换器(首选),您可以使用以下语法强制它:var def = new UInt64(); string json = "18446744073709551615"; object parsedObject = JsonConvert.DeserializeAnonymousType<ulong>(json, def);

标签: c# parsing json.net biginteger uint64


【解决方案1】:

您的问题是 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 反序列化为的 - 一些足以捕获传入 JSON 的 .Net 类型。由于 BigInteger 足以捕获传入的 JSON,Newtonsoft 恰好选择了该类型而不是 Uint64

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

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

演示小提琴here.

【讨论】:

    【解决方案2】:

    我使用了这个例子,并认为我会将它推进到一个类列表中:

    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 的列表,然后将其解析回它在消费者中匹配的类

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-14
      相关资源
      最近更新 更多