我有一个 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 问题也可能得到解决。
您获得的格式是 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'"
};
Startup.cs
:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddJsonOptions(options =>
options.SerializerSettings.Converters.Add(new IsoDateTimeConverter
{
DateTimeStyles = DateTimeStyles.AdjustToUniversal
}));
string json = JsonConvert.SerializeObject(DateTime.Now, new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc
});
处理程序类:
/// <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 标准。