Home > .NET, C# > DateOnly and TimeOnly support with System.Text.Json

DateOnly and TimeOnly support with System.Text.Json

In .NET 6.0 we finally have DateOnly and TimeOnly, two long-awaited data types that allow to store, respectively, only a date (i.e., a birth date or an invoice date) or a time in day (for example, a recurring time for a meeting).

Unfortunately, System.Text.Json doesn’t provide built-in support for these new types. This means that, if we try to serialize a DateOnly or TimeOnly property, we got a NotSupportedException:

NotSupportedException when trying to serialize a DateOnly or TimeOnly property

NotSupportedException when trying to serialize a DateOnly or TimeOnly property

To overcome this issue, we need to create two ad-hoc Converters to handle these types, inherithing the JsonConverter class:

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));
}

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));
}

In this way, we can make the serialization/deserialization work just adding the Converters to a JsonSerializerOptions instancee:


var date = DateOnly.FromDateTime(DateTime.Now);
var time = TimeOnly.FromDateTime(DateTime.Now);

var test = new DataTypeTest(date, time);

var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
options.Converters.Add(new DateOnlyConverter());
options.Converters.Add(new TimeOnlyConverter());

var json = System.Text.Json.JsonSerializer.Serialize(test, options);
var testBack =
    System.Text.Json.JsonSerializer.Deserialize<DataTypeTest>(json, options);

public record DataTypeTest(DateOnly Date, TimeOnly Time);

If you don’t want to add these Converters to all of your projects, you can use my small library, TinyHelpers, that is available on GitHub and NuGet and, among the other things, already provides them, as well as some other cool stuff 🙂

Categories: .NET, C# Tags: , ,

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: