Friday, 29 June 2018

A simple C# JsonConverter example - bool to bit

Newtonsoft Json.NET is a great framework for serialising/de-serialising your Json with .Net, it has a good collection of default handlers for transforming data-types, but what if you would like to override the way in which a property is written/read.

In this example we will change the way that boolean properties are handled, so that they are read and written as 1 or 0 as opposed to the default "True" or "False".


Luckily there is an attribute to help us out with this called JsonConverter which can be used as follows:

[JsonProperty("my_bool")]
[JsonConverter(typeof(BoolToBitJsonConverter))]
public bool MyBool { get; set; }

Notice that we pass the type of BoolToBitJsonConverter.  We will need to implement this class to provide the behaviour that we want, we do this as-follows:

using System;
using Newtonsoft.Json;

namespace MyNamespace
{
   /// <summary>
   /// Ensures that boolean parameters can be read from Json
   /// </summary>
   public class BoolToBitJsonConverter : JsonConverter
   {
      /// <summary>
      /// Ensures that this is decorating a boolean type property
      /// </summary>
      /// <param name="objectType">The type of the decorated property</param>
      /// <returns>True if the property can be converted</returns>
      public override bool CanConvert(Type objectType)
      {
         return typeof(bool) == objectType;
      }

      /// <summary>
      /// Reads a JSON field into a boolean property
      /// </summary>
      /// <param name="reader">Json reader</param>
      /// <param name="objectType">Type of the object we are reading</param>
      /// <param name="existingValue">Existing value of object being read</param>
      /// <param name="serializer">The serialiser calling this method</param>
      /// <returns>Boolean representation of the Json as an object</returns>
      public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
      {
         //If we have a 1 in the Json provided, then we will take that as true, anything else will cause a default to false
         return reader.Value.ToString().Equals("1", StringComparison.InvariantCultureIgnoreCase);
      }

      /// <summary>
      /// Writes the decorated boolean property as a 1 or a 0, instead of True or False respectively
      /// </summary>
      /// <param name="writer">Writer used to output value</param>
      /// <param name="value">The value of the property</param>
      /// <param name="serializer">The serialiser calling this method</param>
      public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
      {
         //Determine if the value is True (1) or False (0)
         int bitVal = Convert.ToBoolean(value) ? 1 : 0;
         writer.WriteValue(bitVal);
      }
   }
}

Hopefully the code is pretty easy to follow, but in essence, the CanConvert method will check to make sure that we have annotated a boolean type parameter, the ReadJson method is for taking the Json value and setting our property based on that & the WriteJson method takes our property value which we can use to output whatever we want to the Json object.

Hope this helps someone out there.

No comments:

Post a Comment