英文:
C# JObject.Parse treats numbers as int64 instead of uint64
问题
If the given json str has the attribute
"seed":11405418255883340000
Error will be thrown: JsonReaderException: JSON integer 11405418255883340000 is too large or small for an Int64
As you'll notice, 11405418255883340000 is too big for int64. But is a legitimate uint64.
Is this a bug or expected? What's the easiest workaround?
英文:
var jobject = JObject.Parse(str);
If the given json str has the attribute
"seed":11405418255883340000
Error will be thrown: JsonReaderException: JSON integer 11405418255883340000 is too large or small for an Int64
As you'll notice, 11405418255883340000 is too big for int64. But is a legitimate uint64.
Is this a bug or expected? What's the easiest workaround?
答案1
得分: 1
以下是翻译好的内容:
最简单的方法可能是创建一个与您期望的负载匹配的DTO,然后将种子属性的类型设置为ulong
。
这是一个示例DTO:
public class Seeder {
public ulong Seed {get;set;}
}
这是如何使用它的,而不是使用Parse:
void Main()
{
var str = "{\"seed\":11405418255883340000}";
var ser = new JsonSerializer();
var jr = new JsonTextReader(new StringReader(str));
var seed = ser.Deserialize<Seeder>(jr);
seed.Dump();
}
这是LinqPad显示的内容:
如果我将属性类型更改回long
,我会得到以下异常:
将值11405418255883340000转换为类型'System.Int64'时出错。路径'seed',行1,位置28。
请注意,您不必编写一个完全指定的DTO对象。这个也可以工作,我们只是在DTO类上没有seed属性:
void Main()
{
var str = "{\"seed\":11405418255883340000, \"bar\": 4}";
var ser = new JsonSerializer();
var jr = new JsonTextReader(new StringReader(str));
var seed = ser.Deserialize<Seeder>(jr);
seed.Dump();
}
public class Seeder {
public int Bar {get;set;}
}
如果您懒得做,可以将JSON负载放入在线类生成器和/或您的IDE中的工具中。有关此方面的起点,请参见:https://stackoverflow.com/a/21611680
英文:
The easiest is probably to create a DTO that matches the payload you expect and then set the type to ulong
of the seed property.
Here is an example DTO:
public class Seeder {
public ulong Seed {get;set;}
}
And here is how you use it, instead of Parse:
void Main()
{
var str = @"{""seed"":11405418255883340000}";
var ser = new JsonSerializer();
var jr = new JsonTextReader(new StringReader(str));
var seed = ser.Deserialize<Seeder>(jr);
seed.Dump();
}
This is what LinqPad shows me:
If I change the property type back to long
I get this exception:
> Error converting value 11405418255883340000 to type 'System.Int64'. Path 'seed', line 1, position 28.
Note that you don't have to code a fully specified DTO object. This one works as wel, where we simply don't have the seed property on our DTO class:
void Main()
{
var str = @"{""seed"":11405418255883340000, ""bar"": 4}";
var ser = new JsonSerializer();
var jr = new JsonTextReader(new StringReader(str));
var seed = ser.Deserialize<Seeder>(jr);
seed.Dump();
}
public class Seeder {
public int Bar {get;set;}
}
If you are lazy you can drop the JSON payload into an online class generator and/or tooling in your IDE. See for a starting point on that: https://stackoverflow.com/a/21611680
答案2
得分: 1
你需要使用 System.Numerics
以便处理 BigInteger
。默认情况下使用的是 long
而不是 ulong
,所以会发生溢出。然后它会尝试将其解析为 BigInteger
。
在 JSON.Net 源代码 中的注释说
#if HAVE_BIG_INTEGER
// 通过在单独的方法中使用 BigInteger 类型,
// 即使 System.Numerics.BigInteger.Parse 方法丢失,运行时也可以执行 ParseNumber,这在某些版本的 Mono 中发生
[MethodImpl(MethodImplOptions.NoInlining)]
private static object BigIntegerParse(string number, CultureInfo culture)
{
return System.Numerics.BigInteger.Parse(number, culture);
}
#endif
所以如果您可以将该库添加到您的项目中,那么它应该可以工作。
但是最好的方法是像其他答案所说的那样,使用适当的对象模型。
英文:
You need System.Numerics
so that it can handle BigInteger
. The default is to use long
not ulong
, so it will get an overflow. Then it will try to parse it as a BigInteger
.
The comments in the JSON.Net source code say
#if HAVE_BIG_INTEGER
// By using the BigInteger type in a separate method,
// the runtime can execute the ParseNumber even if
// the System.Numerics.BigInteger.Parse method is
// missing, which happens in some versions of Mono
[MethodImpl(MethodImplOptions.NoInlining)]
private static object BigIntegerParse(string number, CultureInfo culture)
{
return System.Numerics.BigInteger.Parse(number, culture);
}
#endif
So if you can add that library to your project then it should work.
But your best bet is to just use a proper object model, like the other answer says.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论