如何让 JSON.NET 将日期/时间序列化为 ISO 8601?

问题描述 投票:0回答:4

我有一个 Web API 应用程序,可以将 JSON 返回给可能未使用 Microsoft 技术的消费者。 当我的控制器以 JSON 形式返回具有 DateTime 属性的对象时,它会以此格式序列化日期:

2017-03-15T00:00:00-04:00

这让消费者有点头疼,因为他们期望它采用 ISO 8601 格式。 一些研究告诉我,JSON.NET 现在默认使用 ISO 8601(我使用的是 9.0.1)。 当我运行这段代码时...

Clipboard.Copy(JsonConvert.SerializeObject(DateTime.Now));

...我明白了:

2017-03-15T09:10:13.8105498-04:00

维基百科在表达完整日期和时间时将这些显示为有效的 ISO 8601 格式:

2017-03-15T11:45:42+00:00
2017-03-15T11:45:42Z
20170315T114542Z

但是,我上面得到的输出与其中任何一个都不完全匹配。 我希望格式化程序使用

2017-03-15T11:45:42Z

并且可能完全值得另一个问题,在我的 Web API 配置中添加以下行似乎被忽略,因为它继续在上面最初显示的日期中返回 JSON:

config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter());

我想一旦我弄清楚了核心问题,Web API 问题也可能得到解决。

json asp.net-web-api json.net iso8601
4个回答
34
投票

您获得的格式是 ISO 8601 格式(请阅读维基百科中有关时间和时区指示符的部分),只是您的日期显然没有调整为 UTC 时间,因此您会在日期后附加时区偏移量而不是 Z

 祖鲁时区指示器。

IsoDateTimeConverter

 具有可用于自定义其输出的设置。  您可以通过将 
DateTimeStyles
 设置为 
AdjustToUniversal
,使其自动将日期调整为 UTC。  如果您不需要,您还可以自定义输出格式以省略秒小数部分。  默认情况下,转换器不会调整为 UTC 时间,并且包含与秒可用的尽可能多的精度小数。

试试这个:

IsoDateTimeConverter converter = new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AdjustToUniversal, DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ssK" }; config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(converter);

如果您的日期已经是 UTC,但其上的

DateTimeKind

 未设置为应有的 
Utc
(例如,它是 
Unspecified
),那么理想情况下,您应该修复您的代码,以便在之前正确设置该指示器序列化。  但是,如果您不能(或不想)这样做,您可以通过更改转换器设置以始终在日期格式中包含 
Z
 指示符(而不是使用 
K
 说明符来解决此问题)查看日期上的 
DateTimeKind
)并删除 
AdjustToUniversal
 指令。

IsoDateTimeConverter converter = new IsoDateTimeConverter { DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'" };
    

4
投票
添加@Brian Rogers的答案,对于ASP Core,添加

Startup.cs

services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddJsonOptions(options => options.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AdjustToUniversal }));
    

3
投票
另一种选择:

string json = JsonConvert.SerializeObject(DateTime.Now, new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Utc });
    

0
投票
要将 DateTime 序列化和反序列化处理为 JSON 中的 ISO 8601 字符串,您可以创建一个自定义 JsonConverter 并使用 AddJsonOptions 在 Program.cs 中注册它。

处理程序类:

/// <summary> /// Converts DateTime to and from ISO 8601 strings in JSON. /// </summary> public class JsonIsoDateTimeConverter : JsonConverter<DateTime> { private const string IsoFormat = "yyyy-MM-ddTHH:mm:ss.fffffffZ"; public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return DateTime.Parse(reader.GetString()); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToUniversalTime().ToString(IsoFormat)); } }

Program.cs中的配置:

builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new JsonIsoDateTimeConverter()); });
通过使用此自定义 JsonIsoDateTimeConverter,所有 DateTime 值都将序列化为 ISO 8601 格式或反序列化为 ISO 8601 格式(例如“2024-07-18T09:30:00.0000000Z”),确保符合 ISO-8601 标准。

© www.soinside.com 2019 - 2024. All rights reserved.