System.FormatException: The JSON value is not in a supported DateTimeOffset format

Viewed 5056

I was reading this MSDocs article about DateTime-related format support https://docs.microsoft.com/en-us/dotnet/standard/datetime/system-text-json-support#support-for-the-iso-8601-12019-format

And I was trying to play around just to figure out that the default configuration wasn't working as expected or I must be missing something out.

I mean:

DateTimeOffset.Parse("2021-03-17T12:03:14+0000");

Works just fine.

BUT

JsonSerializer.Deserialize<TestType>(@"{ ""CreationDate"": ""2021-03-17T12:03:14+0000"" }");

Doesn't.

Example:

using System;
using System.Text.Json;
using System.Threading.Tasks;


namespace CSharpPlayground
{
    public record TestType(DateTimeOffset CreationDate);
    
    public static class Program
    {
        public static void Main()
        {
            var dto = DateTimeOffset.Parse("2021-03-17T12:03:14+0000");
            Console.WriteLine(dto);

            var testType = JsonSerializer.Deserialize<TestType>(@"{ ""CreationDate"": ""2021-03-17T12:03:14+0000"" }");
            Console.WriteLine(testType.CreationDate);
        }
    }
}

The exception below is thrown:

System.Text.Json.JsonException: The JSON value could not be converted to CSharpPlayground.TestType. Path: $.CreationDate | LineNumber: 0 | BytePositionInLine: 44.
 ---> System.FormatException: The JSON value is not in a supported DateTimeOffset format.
1 Answers

Implementing custon JSON behaviours with System.Text.Json is usually done with custom converters. Unfortunately there aren't many provided out the box for different date formats, so if you need to deserialise something not in the default ISO 8601-1:2019 format you need to roll your own.

Forutnately that's not very difficult:

   using System.Text.Json;
   using System.Text.Json.Serialization;

    public class DateTimeOffsetConverterUsingDateTimeParse : JsonConverter<DateTimeOffset >
    {
        public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            Debug.Assert(typeToConvert == typeof(DateTimeOffset));
            return DateTimeOffset .Parse(reader.GetString());
        }

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

This way you'll the same behaviour you do when you use DateTimeOffset.Parse().

You can use it like this

    public record TestType(DateTimeOffset CreationDate);
    public class Program
    {
        public static void Main(string[] args)
        {
            JsonSerializerOptions options = new JsonSerializerOptions();
            options.Converters.Add(new DateTimeOffsetConverterUsingDateTimeParse());
            
            var testType = JsonSerializer.Deserialize<TestType>(@"{ ""CreationDate"": ""2021-03-17T12:03:14+0000"" }",options);
            Console.WriteLine(testType.CreationDate);
        }
    }
    

Related