json.net-coresystem.text.json

Deserialize scientific notation to long with System.Text.Json


I have JSON with a number in scientific notation, e.g. 1.83E+2. Deserializing it with Json.NET to a long has worked well for me, but when I replace the deserializer with the new one in System.Text.Json it throws an JsonException:

System.Text.Json.JsonException: 'The JSON value could not be converted to System.Int64. ...'

Here is a reproducible example:

static void Main()
{
    // test1 is 183
    var test1 = Newtonsoft.Json.JsonConvert.DeserializeObject<Foo>(@"{""Bar"": 1.83E+2}"); 

    // throws JsonException
    var test2 = System.Text.Json.JsonSerializer.Deserialize<Foo>(@"{""Bar"": 1.83E+2}");
}

public class Foo
{
    public long Bar { get; set; }
}

Solution

  • After asking the .NET Core team they provided this solution to the problem:

    static void Main()
    {
        var options = new JsonSerializerOptions
        {
            Converters = { new CustomInt64Converter() }
        };
    
        // test1 is 183
        var test1 = Newtonsoft.Json.JsonConvert.DeserializeObject<Foo>(@"{""Bar"": 1.83E+2}");
    
        // test2 is 183
        var test2 = System.Text.Json.JsonSerializer.Deserialize<Foo>(@"{""Bar"": 1.83E+2}", options);
    }
    
    public class Foo
    {
        public long Bar { get; set; }
    }
    
    public class CustomInt64Converter : JsonConverter<long>
    {
        public override long Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return reader.TryGetInt64(out var result) ? result : Convert.ToInt64(reader.GetDecimal());
        }
    
        public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options)
        {
            writer.WriteNumberValue(value);
        }
    }