gpt4 book ai didi

c# - 对于没有时区的 DateTimeOffset.MinValue,Json.NET 反序列化 DateTimeOffset 值失败

转载 作者:太空狗 更新时间:2023-10-29 23:12:22 26 4
gpt4 key购买 nike

在我的 ASP.NET Core Web-API 项目中,我收到了对我的一个 API Controller 的 HTTP POST 调用。

在评估 JSON 负载并反序列化其内容时,Json.NET 偶然发现了 0001-01-01T00:00:00 的 DateTime 值,并且无法将其转换为 DateTimeOffset 属性。

我注意到该值应该代表 DateTimeOffset.MinValue 的值,但它缺少时区似乎会使解串器出错。我只能想象 DateTimeOffset.Parse 会尝试将其转换为主机当前时区,这会导致 DateTimeOffset.MinValue 下溢。

这个属性非常简单:

[JsonProperty("revisedDate", NullValueHandling = NullValueHandling.Ignore)]
public DateTimeOffset? RevisedDate { get; set; }

这是发送给客户端的响应:

{
"resource.revisedDate": [
"Could not convert string to DateTimeOffset: 0001-01-01T00:00:00. Path 'resource.revisedDate', line 20, position 44."
]
}

我正在使用 Newtonsoft.Json v11.0.2,目前处于 UTC + 2(德国)。异常回溯和错误消息在这里:https://pastebin.com/gX9R9wq0 .

我无法修复调用代码,所以我必须在我这边修复它。

但问题是:怎么做?

最佳答案

问题 似乎只有在机器的时区 TimeZoneInfo.Local 时才能重现与 UTC 有正偏移,例如(UTC+01:00) 阿姆斯特丹、柏林、伯尔尼、罗马、斯德哥尔摩、维也纳。我无法在具有非正偏移量的时区重现它,例如 UTC-05:00 或 UTC 本身。

具体来说,在 JsonReader.ReadDateTimeOffsetString()使用 DateTimeStyles.RoundtripKind 调用 DateTimeOffset.TryParse:

if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
SetToken(JsonToken.Date, dt, false);
return dt;
}

这显然会导致具有正 UTC 偏移量的时区出现下溢错误。如果在调试器中我使用 DateTimeStyles.AssumeUniversal 进行解析,则可以避免该问题。

您可能想要 report an issue关于这个给 Newtonsoft。只有当计算机的时区具有特定值时,特定 DateTimeOffset 字符串的反序列化才会失败这一事实似乎是错误的。

解决方法是使用 IsoDateTimeConverter使用 IsoDateTimeConverter.DateTimeStyles 反序列化您的 DateTimeOffset 属性设置为 DateTimeStyles.AssumeUniversal。此外,有必要通过设置 JsonReader.DateParseHandling = DateParseHandling.None 来禁用 JsonReader 内置的自动 DateTime 识别功能。 ,这必须在阅读器开始解析您的 DateTimeOffset 属性的值之前完成。

首先,定义如下JsonConverter:

public class FixedIsoDateTimeOffsetConverter : IsoDateTimeConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?);
}

public FixedIsoDateTimeOffsetConverter() : base()
{
this.DateTimeStyles = DateTimeStyles.AssumeUniversal;
}
}

现在,如果您可以修改 Controller 的 JsonSerializerSettings,请使用以下设置:

var settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None,
Converters = { new FixedIsoDateTimeOffsetConverter() },
};

如果您不能轻松修改 Controller 的JsonSerializerSettings,则需要从this answer 获取DateParseHandlingConverter How to prevent a single object property from being converted to a DateTime when it is a string 并将其与 FixedIsoDateTimeOffsetConverter 一起应用于您的模型,如下所示:

[JsonConverter(typeof(DateParseHandlingConverter), DateParseHandling.None)]
public class RootObject
{
[JsonProperty("revisedDate", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(FixedIsoDateTimeOffsetConverter))]
public DateTimeOffset? RevisedDate { get; set; }
}

DateParseHandlingConverter 必须应用于模型本身而不是 RevisedDate 属性,因为 JsonReader 已经识别出 0001-01 -01T00:00:00 作为调用 FixedIsoDateTimeOffsetConverter.ReadJson() 之前的 DateTime

更新

comments , @RenéSchindhelm写道,我创建了一个问题让 Newtonsoft 知道。它是 Deserialization of DateTimeOffset value fails depending on system's timezone #1731 .

关于c# - 对于没有时区的 DateTimeOffset.MinValue,Json.NET 反序列化 DateTimeOffset 值失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50628374/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com