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

Eho*_*ret 10 .net c# json datetimeoffset system.text.json

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

我试图弄清楚默认配置没有按预期工作,或者我一定错过了一些东西。

我是说:

DateTimeOffset.Parse("2021-03-17T12:03:14+0000");
Run Code Online (Sandbox Code Playgroud)

效果很好。

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

没有。

例子:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

抛出以下异常:

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.
Run Code Online (Sandbox Code Playgroud)

小智 17

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

Run Code Online (Sandbox Code Playgroud)

这样,您将获得与使用 时相同的行为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);
        }
    }
    

Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但是您的 Write 方法中有一个错误。应该是: public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString("O")); } (3认同)