JSON serialization of TimeOnly and DateOnly types in .NET 6

Joseph Izang
2 min readApr 16, 2022
Conveyor chain and gear on a wooden platform
Photo by LouisMoto on Unsplash

In case you are having trouble serializing the new types in .NET 6 using System.Text.Json namespace to convert DateOnly and TimeOnly types, then you are not alone. I found this after dealing with using DateOnly and TimeOnly types while using Npgsql with a Blazor app I was working on.

It turns out that you will have to write a custom converter that will handle serialization of these types to JSON and back. I checked and tried to hand roll one myself. Luckily, I found some inspiration from an msdn blog post, not sure whose it is, as I cannot find the site at the moment, but it helped me along the right path. I have these two classes to do the work for me.

public class DateOnlyConverter : JsonConverter<DateOnly>{private readonly string serializationFormat;public DateOnlyConverter() : this(null){}public DateOnlyConverter(string? serializationFormat){this.serializationFormat = serializationFormat ?? "yyyy-MM-dd";}public override DateOnly Read(ref Utf8JsonReader reader,Type typeToConvert, JsonSerializerOptions options){var value = reader.GetString();return DateOnly.Parse(value!);}public override void Write(Utf8JsonWriter writer, DateOnly value,JsonSerializerOptions options)=> writer.WriteStringValue(value.ToString(serializationFormat));}

This is the DateOnlyConverter class that does the obvious. And here is the TimeOnlyConverter class.

public class TimeOnlyConverter : JsonConverter<TimeOnly>{private readonly string serializationFormat;public TimeOnlyConverter() : this(null){}public TimeOnlyConverter(string? serializationFormat){this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff";}public override TimeOnly Read(ref Utf8JsonReader reader,Type typeToConvert, JsonSerializerOptions options){var value = reader.GetString();return TimeOnly.Parse(value!);}public override void Write(Utf8JsonWriter writer, TimeOnly value,JsonSerializerOptions options)=> writer.WriteStringValue(value.ToString(serializationFormat));}

You would then add this to your Startup.cs if its an old style .NetCore app:

public void ConfigureServices(IServiceCollection services){...services.AddControllers().AddJsonOptions(options =>{options.JsonSerializerOptions.Converters.Add(new DateOnlyConverter());options.JsonSerializerOptions.Converters.Add(new TimeOnlyConverter());});...}

Or if you prefer the minimal API way of doing things then:

builder.Services.Configure<JsonOptions>(options =>{
...
options.SerializerOptions.Converters.Add(new DateOnlyConverter());options.SerializerOptions.Converters.Add(new TimeOnlyConverter());
...
});

After this, you can be on your merry way and DateOnly and TimeOnly won’t be a problem.

Cherrio and God bless.

--

--

Joseph Izang

I love Jesus Christ. Love my family. I love code, art & music.