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

1

12

I was reading this MSDocs article about DateTime-related format support https://learn.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.
Jollanta answered 6/6, 2021 at 8:10 Comment(5)
Please do not put tags in your question titles (the tagging help section is pretty explicit about this, and goes as far as listing exampel formats you shouldn't use).Metaxylem
I expect the issue is with +0000, with the expected value being +00:00. I can't advise how to solve this since I'm not really familiar with System.Text.Json, but it might involve writing a custom converter. I found a GitHub issue relating to this hereMetaxylem
@Llama thanks for pointing this out, and sorry.Jollanta
FYI, when you are using hyphens and colons in the timestamp, ISO 8601 calls that the "extended" format, and that also requires a colon in the offset component. The "basic" format doesn't use hyphens or colons in any of the components. Mixing the two is not allowed by the spec, so your string as shown here is not ISO 8601 compliant.Chaplet
@MattJohnson-Pint FYI this comes from a PSP I have to deal and I didn't get to decide how they are implementing their APIs... Also it's far from being the only thing off. And I have no say on which PSP I have to use at work. "Voila"Jollanta
U
18

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

Ullman answered 6/6, 2021 at 9:18 Comment(2)
Oh thanks, I thought the format I was trying to parse was part of the standard, my bad. Thanks again for your answer, really appreciated!Jollanta
Good answer, but there is a bug in your Write method. Should be: public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString("O")); }Antitragus

© 2022 - 2025 — McMap. All rights reserved.