How can I force the minimum number of decimal places in Json.net?

I get annoying inconsistency when I write json decimal words using json.net. Sometimes it is up to 1 dp, other times 2.

Obviously, I know solutions for outputting decimals to strings with a certain number of decimals such as this , but you don't have this control using json.NET without writing a custom serializer, I think.

I also know that Math.Roundto ensure the maximum number of decimal places, this issue is related to ensuring the minimum number of decimal places.

The first two tests show what is happening, it keeps the original number of decimal places from declaration or calculation.

I found that I can add and then subtract the small fraction that the next two tests show, but is there a cleaner way?

[TestFixture]
public sealed class DecimalPlaces
{
    public class JsonType
    {
        public decimal Value { get; set; }
    }

    [Test]
    public void TwoDp()
    {
        var obj = new JsonType { Value = 1.00m };
        Assert.AreEqual("{\"Value\":1.00}", JsonConvert.SerializeObject(obj));
    }

    [Test]
    public void OneDp()
    {
        var json = new JsonType { Value = 1.0m };
        Assert.AreEqual("{\"Value\":1.0}", JsonConvert.SerializeObject(obj));
    }

    private decimal ForceMinimumDp(decimal p, int minDecimalPlaces)
    {
        decimal smallFrac = 1m/((decimal)Math.Pow(10, minDecimalPlaces));
        return p + smallFrac - smallFrac;
    }

    [Test]
    public void ForceMinimumTwoDp()
    {
        var obj = new JsonType { Value = ForceMinimumDp(1.0m, 2) };
        Assert.AreEqual("{\"Value\":1.00}", JsonConvert.SerializeObject(obj));
    }

    [Test]
    public void ForceMinimumThreeDp()
    {
        var obj = new JsonType { Value = ForceMinimumDp(1.0m, 3) };
        Assert.AreEqual("{\"Value\":1.000}", JsonConvert.SerializeObject(obj));
    }
}
+8
source share
1 answer

You can do this with a custom JSON converter:

class DecimalJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof (decimal);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(((decimal) value).ToString("F2", CultureInfo.InvariantCulture));
    }
}

This is a very simple converter. You may need to expand it to support other floating point types, or perhaps even integer types.

Now create an instance of your serializer and pass it your own converter, for example:

var serializer = new JsonSerializer();
serializer.Converters.Add(new DecimalJsonConverter());
+10
source

Source: https://habr.com/ru/post/1622534/


All Articles