Home > Enterprise >  Deserializing DateOnly
Deserializing DateOnly

Time:07-15

I have this record that I'm trying to deserialize:

public record MementoTimeEntry
(
    Guid Id,
    Guid ActivityId,
    string UserId,
    string Title,
    TimeOnly StartTime,
    TimeOnly FinishTime,
    DateOnly Start,
    DateOnly ActivityDate,
    int Hours
);

However, I get this error:

System.NotSupportedException: Serialization and deserialization of 'System.DateOnly' instances are not supported.

Which is thankfully pretty clear what the issue is.

So, I've read this answer and this GitHub thread. However, neither seem to provide the full answer. Both make reference to a DateOnlyConverter but I can't seem to find this anywhere in the framework.

I've previously used the [JsonPropertyConverter(typeof(CustomConverter))] attribute to achieve similar things.

So my question really boils down to:

Is this DateOnlyConverter something that already exists, or am I going to have to implement it myself?

If the answer is the latter, I'll do it and then post it as an answer to this question for future readers.

CodePudding user response:

The converter will be released with .NET 7.

For now you can create a custom one looking something like this (for System.Text.Json, for Json.NET - see this answer):

public class DateOnlyJsonConverter : JsonConverter<DateOnly>
{
    private const string Format = "yyyy-MM-dd";

    public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateOnly.ParseExact(reader.GetString(), Format, CultureInfo.InvariantCulture);
    }

    public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString(Format, CultureInfo.InvariantCulture));
    }
}

And one of the possible usages would be:

class DateOnlyHolder
{
    // or via attribute [JsonConverter(typeof(DateOnlyJsonConverter))]
    public DateOnly dt { get; set; }
}

var jsonSerializerOptions = new JsonSerializerOptions
{
    Converters = { new DateOnlyJsonConverter() }
};
    
var serialized = JsonSerializer.Serialize(new DateOnlyHolder{dt = new DateOnly(2022,1,2)}, jsonSerializerOptions);
Console.WriteLine(serialized); // prints {"dt":"2022-01-02"}
var de = JsonSerializer.Deserialize<DateOnlyHolder>(serialized, jsonSerializerOptions);
Console.WriteLine(de.dt); // prints 1/2/2022
  • Related