System.FormatException: JSON 值不是受支持的 DateTimeOffset 格式

问题描述

我正在阅读这篇关于日期时间相关格式支持的 MSDocs 文章 https://docs.microsoft.com/en-us/dotnet/standard/datetime/system-text-json-support#support-for-the-iso-8601-12019-format

而我只是想弄清楚认配置没有按预期工作,或者我一定遗漏了一些东西。

我的意思是:

employee_id

工作正常。

但是

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

没有。

示例:

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

抛出以下异常:

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

解决方法

使用 System.Text.Json 实现自定义 JSON 行为通常是通过自定义转换器完成的。不幸的是,对于不同的日期格式并没有提供很多开箱即用的格式,因此如果您需要反序列化不是默认 ISO 8601-1:2019 格式的内容,您需要自己动手。

幸运的是,这不是很困难:

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

这样,您的行为与使用 DateTimeOffset.Parse() 时的行为相同。

你可以这样使用

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