Brian Agnew
Brian Agnew

Reputation: 272437

How to parse JSON decimals correctly using ServiceStack JsonSerializer

I have the following scenario:

var json = "{\"AccruedInterest\":9.16666666666666E-6}";
var result = JsonSerializer.DeserializeFromString<MyResult>(json);
Assert.That(result .AccruedInterest, Is.GreaterThan(0m));

where MyResult declares the field AccruedInterest as a decimal

The above test sets AccruedInterest to 0 and consequently fails. If I set the JSON to anything other than an accrued interest value with an exponent then the test works.

Is the ServiceStack JSON handling of JSON string to decimals broken? The above appears to be perfectly valid JSON (using exponents etc.)

Upvotes: 1

Views: 1233

Answers (1)

Mike
Mike

Reputation: 1837

If you switch the type on your MyResult class to a float you will get the results you expect:

public class Program
{
    public static void Main(string[] args)
    {
        const string json = "{\"AccruedInterest\":9.16666666666666E-6}";
        var result = JsonSerializer.DeserializeFromString<MyResult>(json);
    }
}

public class MyResult
{
    public float AccruedInterest { get; set; }
}

The reason for this can be found in DeserializeBuiltin:

if (typeof(T) == typeof(decimal))
    return value => decimal.Parse(value, CultureInfo.InvariantCulture);

If you try and do the parse yourself you will get an invalid format exception.

decimal.Parse("9.16666666666666E-6", CultureInfo.InvariantCulture);

If you specify a number style of float the exception will go away.

decimal.Parse("9.16666666666666E-6", NumberStyles.Float, CultureInfo.InvariantCulture);

Likewise parsing it as a float works:

float.Parse("9.16666666666666E-6", CultureInfo.InvariantCulture);

Upvotes: 3

Related Questions