Thursday 22 April 2021

How to create custom converters for JSON serialization in dotnetcore?

If you are developing asp.net core web API and somehow getting requirements to accept custom bool value from the request. Like instead of true, false, 0, and 1 it should accept "True", "0", "1", "Y", and others. You can do it easily by creating custom converters that are available in both System.Text.Json and NewtonSoft.

Sharing snippet by using which I achieved it. 

Created a simple BooleanConverter

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
 
namespace JsonHelpers
{
    public class BooleanConverter : JsonConverter<bool>
    {
       
        
        public override bool ReadJson(JsonReader reader, Type objectType, [AllowNull] bool existingValue, bool hasExistingValue, Newtonsoft.Json.JsonSerializer serializer)
        {
         
            string boolValue = reader.Value?.ToString().ToLower();
            if (boolValue.Equals("true") || boolValue.Equals("yes") || boolValue.Equals("y") || boolValue.Equals("1"))
            {
                return true;
            }
            if (boolValue.Equals("false") || boolValue.Equals("no") || boolValue.Equals("n") || boolValue.Equals("0"))
            {
                return false;
            }
            throw new Newtonsoft.Json.JsonException($"{reader.Path}:{boolValue}, Invalid Boolean.");
        }
 
         
 
        public override void WriteJson(JsonWriter writer, [AllowNull] bool value, Newtonsoft.Json.JsonSerializer serializer)
        {
            switch (value)
            {
                case true:
                    writer.WriteRawValue("true");
                    break;
                case false:
                    writer.WriteRawValue("false");
                    break;
 
            }
        }
    }
}

And in .netcore start.cs added 

services.AddControllers().AddNewtonsoftJson(options =>
{
    options.SerializerSettings.Converters.Add(new BooleanConverter());
    options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});

And your Dto should deserialize properly even if you send "y" and "1".

If you are deserializing manually then you can do it like this
var obj = JsonConvert.DeserializeObject<MyDto>(jsonString , new BooleanConverter());