I've got some json with huge integers, in the order of a few hundred digits. I'd like to parse those as BouncyCastle's BigInteger
(https://github.com/onovotny/BouncyCastle-PCL/blob/pcl/crypto/src/math/BigInteger.cs).
{
"bigNumber":12093812947635091350945141034598534526723049126743245...
}
So I've implemented a converter, using a contract resolver in the default settings.
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()
};
The writer works as it should, writing a (large) integer value instead of the class BigInteger with all its properties etc. However, the reading fails. Neither ReadJson nor CanConvert appear to be invoked.
I get the following exception:
JsonReaderException: JSON integer 340597435091750914358634185762341897561435984635897436598435643875643189576413589743659817456... is too large or small for an Int64.
How do I get Json.NET to parse this number as a string instead of an integer?
Ideally I don't want to have to parse the json string myself first, to add quotes.
If your large number isn't quoted, Json.Net will deserialize it as a System.Numerics.BigInteger
. This happens inside the JsonTextReader
, well before the converter gets a chance to handle it. So if you want your result type to be Org.BouncyCastle.Math.BigInteger
, you'll need to convert from System.Numerics.BigInteger
. (Seems a little backwards, I know. The other alternative is to create your own JsonTextReader
, but that is probably going to be more trouble than it is worth -- most of the useful bits of the existing reader are in private or internal methods, so subclassing it is not practical.)
I was able to get this converter to work:
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());
}
}
Here is the test program I used. Note that I did not use a resolver. JsonSerializerSettings
has a Converters
collection, so I just added the BigIntegerConverter
to that.
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; }
}
Output:
12093812947635091350945141034598534526723049126743245
You can try creating object that handles the output of the json like this:
public class YourModel
{
[JsonConverter(typeof(CustomConverter<BigInteger>))]
public BigInteger YourProperty{ get; set; }
}
And now it can become more generic for every type you need:
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 ...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With