Ren*_*elm 5 c# datetimeoffset json.net deserialization asp.net-core-mvc
在我的ASP.NET Core Web-API项目中,我正在对我的一个API控制器进行HTTP POST调用。
在评估JSON有效负载并反序列化其内容时,Json.NET偶然发现DateTime值为,0001-01-01T00:00:00并且无法将其转换为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。
我无法修复调用代码,因此必须在行的一侧进行修复。
但是问题是:如何?
这是我用来解决 .NET Core 3 中的问题的方法。
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers()
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
                options.SerializerSettings.DateParseHandling = DateParseHandling.None;
                options.SerializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal });
            });
...
仅当机器的时区TimeZoneInfo.Local与UTC的偏差为正时,该问题才可重现(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna。我无法在带有非正偏移量的时区(例如UTC-05:00UTC本身)中重现它。
具体而言,在JsonReader.ReadDateTimeOffsetString()呼叫中DateTimeOffset.TryParse使用DateTimeStyles.RoundtripKind:
if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
{
    SetToken(JsonToken.Date, dt, false);
    return dt;
}
这显然会在具有正UTC偏移量的时区中引起下溢错误。如果在调试器中我使用解析DateTimeStyles.AssumeUniversal,则可以避免该问题。
您可能需要向Newtonsoft 报告有关此问题。DateTimeOffset仅当计算机的时区具有特定值时,特定字符串的反序列化才会失败的事实似乎是错误的。
解决方法是使用设置为IsoDateTimeConverter来反序列化DateTimeOffset属性。此外,有必要禁用自动内置到识别的设置,必须做之前,读者开始解析你的价值属性。IsoDateTimeConverter.DateTimeStylesDateTimeStyles.AssumeUniversalDateTimeJsonReaderJsonReader.DateParseHandling = DateParseHandling.NoneDateTimeOffset
首先,定义以下内容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;
    }
}
现在,如果可以JsonSerializerSettings为控制器修改,请使用以下设置:
var settings = new JsonSerializerSettings
{
    DateParseHandling = DateParseHandling.None,
    Converters = { new FixedIsoDateTimeOffsetConverter() },
};
如果你不能轻易修改你的控制器JsonSerializerSettings,你需要抢DateParseHandlingConverter从这个答案到如何防止被转换为当它是一个字符串,一个DateTime一个对象的属性,并将其应用以及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为。DateTimeFixedIsoDateTimeOffsetConverter.ReadJson()
更新资料
在评论,@RenéSchindhelm写道,我创建了一个问题,让Newtonsoft知道。它的DateTimeOffset值的反序列化失败取决于系统的时区#1731。
| 归档时间: | 
 | 
| 查看次数: | 2688 次 | 
| 最近记录: |