用Json.NET读取大整数

时间:2015-10-12 08:10:57

标签: c# json.net

我有一些巨大整数的json,大约有几百个数字。我想将其解析为BouncyCastle BigInteger https://github.com/onovotny/BouncyCastle-PCL/blob/pcl/crypto/src/math/BigInteger.cs)。

{
    "bigNumber":12093812947635091350945141034598534526723049126743245...
}

所以我在默认设置中使用合约解析器实现了转换器。

internal class BigIntegerConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(value.ToString());
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken jToken = JToken.Load(reader);
        return new BigInteger(jToken.ToString());
    }

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(BigInteger));
    }
}

public class BigIntegerContractResolver : DefaultContractResolver
{
    private static readonly JsonConverter bigIntegerConverter = new BigIntegerConverter();
    private static Type type = typeof(BigInteger);

    protected override JsonConverter ResolveContractConverter(Type objectType)
    {
        if (objectType == type)
        {
            return bigIntegerConverter;
        }
        return base.ResolveContractConverter(objectType);
    }
}

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            ContractResolver = new BigIntegerContractResolver()
        };

编写器正常工作,编写一个(大)整数值而不是类BigInteger及其所有属性等。但是,读取失败。似乎没有调用ReadJson和CanConvert。

我得到以下异常:

JsonReaderException:JSON整数340597435091750914358634185762341897561435984635897436598435643875643189576413589743659817456 ...对于Int64来说太大或太小。

如何让Json.NET将此数字解析为字符串而不是整数?

理想情况下,我不想首先自己解析json字符串,以添加引号。

2 个答案:

答案 0 :(得分:3)

如果没有引用您的大号,Json.Net会将其反序列化为JsonTextReader。这发生在Org.BouncyCastle.Math.BigInteger内部,在转换器有机会处理之前。因此,如果您希望结果类型为System.Numerics.BigInteger,则需要转换JsonTextReader。 (我知道,似乎有点倒退了。另一个选择是创建你自己的class BigIntegerConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(Org.BouncyCastle.Math.BigInteger)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { System.Numerics.BigInteger big = (System.Numerics.BigInteger)reader.Value; return new Org.BouncyCastle.Math.BigInteger(big.ToString()); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { writer.WriteRawValue(value.ToString()); } } ,但这可能会比它的价值更麻烦 - 现有读者的大多数有用位都是私有的或者内部方法,所以对它进行子类化是不切实际的。)

我能够让这个转换器工作:

JsonSerializerSettings

这是我使用的测试程序。请注意,我没有使用解析器。 Converters有一个BigIntegerConverter集合,所以我刚刚添加了class Program { static void Main(string[] args) { string json = @" { ""bigNumber"": 12093812947635091350945141034598534526723049126743245 }"; JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = new List<JsonConverter> { new BigIntegerConverter() } }; Foo foo = JsonConvert.DeserializeObject<Foo>(json); Console.WriteLine(foo.BigNumber.ToString()); } } class Foo { public Org.BouncyCastle.Math.BigInteger BigNumber { get; set; } }

12093812947635091350945141034598534526723049126743245

输出:

private void tabControl1_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Right)
    {
        Application.Exit();
    }
    else
    {

    }
}

答案 1 :(得分:1)

您可以尝试创建处理json输出的对象,如下所示:

public class YourModel
{
    [JsonConverter(typeof(CustomConverter<BigInteger>))]
    public BigInteger YourProperty{ get; set; }
}

现在,对于您需要的每种类型,它都可以变得更通用:

public class CustomConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        your code ..
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        //explicitly specify the concrete type we want to create
        return serializer.Deserialize<T>(reader);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        your code ...
    }
}