A custom Json.NET converter

Sometimes, the incoming data in JSON has some custom form that is not supported by the built-in Json.NET converters. In this article, as an educational example, we will implement a custom converter from the UNIX time format in milliseconds to the native .NET class DateTime.

As a quick remark, it is needed to say, that starting from version 11.0 the Json.NET supports such conversion using the UnixDateTimeConverter. However, it converts only to/from seconds.

In our case, we will use a timestamp in milliseconds, and make support of both, nullable and not nullable, versions of DateTime.

In order to implement a custom converter, we should derive from the class JsonConverter and override three methods:

public class UnixMillisDateTimeConverter : JsonConverter
{
    public override bool CanConvert(Type type)
    {
        // Tells Json.NET what it can convert.
    }
 
    public override object ReadJson(
        JsonReader reader,
        Type type,
        object value,
        JsonSerializer serializer)
    {
        // The logic of reading value from JSON and converting it
        // into .NET object. Value deserialization.
    }
 
    public override void WriteJson(
        JsonWriter writer,
        object value,
        JsonSerializer serializer)
    {
        // The logic of writing .NET object to JSON,
        // value serialization.
    }
}

In the CanConvert() method we are able to check the expected type and tell Json.NET if we can handle it. For example, if the model has a DateTime field, Json.NET passes the DateTime type there to check if the converter can actually convert a value from the JSON into DateTime.

Method ReadJson() contains the logic of how to deserialize the value from JSON. Through the parameter reader we have access to the JSON itself and can control the process of reading. In the simplest case we can get the property value as reader.Value. Note, that this object can be actually one of the primitive types supported by JSON. Speaking about UNIX time, we can expect, that the time is represented in JSON as string (e.g. ‘1531402617’) or as a long (e.g. 1531402617). So, it type should be checked before trying to convert it.

Parameter type tells us the type of model property. In our example it can be DateTime or Nullable<DateTime>.

The WriteJson() method handles the serialization process of the model property. The parameter value contains the current value of the model property. In most cases, we cast it to the actual property type.

The parameter writer allows us to write the actual serialized value to the JSON. Note, that it has a set of handy methods (e.g. WriteNull()) for controlling what should actually appear in the JSON.

The last question, that should be discussed, before we assemble everything in one complete solution, is how to actually convert the UNIX timestamp into DateTime and back. And fortunately, the answer is very simple: starting from .NET 4.6 class DateTimeOffset provides convenient methods ToUnixTimeMilliseconds() and FromUnixTimeMilliseconds().

The complete example of working UnixMillisDateTimeConverter is accessible on GitHub. Feel free to use it 🙂