Deserializing TimeSpan using JsonSerializer

Rewrite

I was researching how to deserialize a TimeSpan using Newtonsoft’s JSON.net and found code in my current project that used System.Text.Json.JsonSerializer instead. This code appeared to not fail on the operation of deserializing the TimeSpan property, as per the unit tests I was running.

To confirm, I ran a test case in the latest version of Linqpad 6 (which uses .NET Core):

public class Project { public TimeSpan AverageScanTime { get; set; } }
var newP = new Project() { AverageScanTime = TimeSpan.FromHours(1) };

newP.Dump("New one");

var json = System.Text.Json.JsonSerializer.Serialize(newP);

json.Dump("JSON serialized");

System.Text.Json.JsonSerializer.Deserialize<Project>(json)
                               .Dump("JSON Deserialize");

Unfortunately, the deserialization failed (see image below).

enter image description here

My question is: can the TimeSpan be serialized/deserialized using either library? If so, how? Or is my test case flawed in some respect?

The issue is that System.Text.Json.JsonSerializer does not support serializing or deserializing TimeSpan objects by default. However, you can create a custom converter to handle TimeSpan objects. Here’s an example:

public class TimeSpanConverter : System.Text.Json.Serialization.JsonConverter<TimeSpan>
{
    public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return TimeSpan.Parse(reader.GetString());
    }

    public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

Then, you can specify this converter when serializing or deserializing Project objects:

var options = new JsonSerializerOptions();
options.Converters.Add(new TimeSpanConverter());

var json = JsonSerializer.Serialize(newP, options);

var newProject = JsonSerializer.Deserialize<Project>(json, options);