Globally Configuring Values For JSON Serializer In ASP.NET Core 3.1

This article will focus on how one can set certain constraints on the given data type for JSON serialization at the application level. This means changes need to be done globally rather than for specific custom classes or properties. We will also see, how one can fall back to default settings, post this application level change. Let’s understand this with the help of an example.

Making application-level changes for JSON serialization

Here the problem statement is, that we want all the float values to be restricted to 3 decimal places. Now, one way to achieve this is to decorate all the float properties in all the model classes with a specific attribute using [JsonConverter(type of (…)].

With the above attribution, one can indeed achieve the goal of conversion or data formatting, but what if there are so many float values across the application? Is it feasible to go and change every single float property under every model class? I feel, NO (

So, the solution to this problem is to do such a setting globally and this can be achieved in two steps, where in the first step we will introduce a class that will take care of conversion or data formatting stuff, and in the second step, we will associate this class with ASP.NET Core services.

Here is the code

Model class

public class Calculate
{
    public float Price { get; set; }
    public float Rate { get; set; }
}

Converter class

public class FloatConverter : JsonConverter<float>
{
    public override float Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, float value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(string.Format("{0:F3}", value));
    }
}

and then a few code changes in the Startup class are as follows

public void ConfigureServices(IServiceCollection services)
{
    // Other service configurations
    services.AddControllersWithViews().AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new FloatConverter());
    });
}

Now, if you run your application, you will notice that all the floats that came out of JSON serialization are shown to 3 decimal places.

Fallback to default settings

Now let's say, there are few float properties in our model class, on which we don't want to apply this global setting. Now, how to solve this?

Well, to make the default settings work, we have to create another converter that will override the global setting and then decorate all those properties with this new converter. This new converter will do nothing more than retain the default behavior. In our example, I don't want to apply any conversion logic for Rate property. So, this is how we can change our model class.

public class Calculate
{
    public float Price { get; set; }
    [JsonConverter(typeof(DefaultFloatConverter))]
    public float Rate { get; set; }
}

and code for DefaultFloatConverter is as follows

public class DefaultFloatConverter : JsonConverter<float>
{
    public override float Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
    public override void Write(Utf8JsonWriter writer, float value, JsonSerializerOptions options)
    {
        writer.WriteNumberValue(value);
    }
}

Now, if you run the application, you will notice that Rate is coming in its default precision, whereas Price is restricted to 3 decimals.

Hope you enjoyed reading.