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 🙂