ASP.NET Web API接收含DateTimeOffset属性实体的POST请求异常
解决ASP.NET Core API解析带无时区冒号的DateTimeOffset格式问题
问题原因
你遇到的问题是因为ASP.NET Core默认使用的System.Text.Json解析器,对DateTimeOffset类型的时区偏移格式有严格要求——必须带冒号(比如-04:00),而你传入的是-0400这种不带冒号的格式,导致JSON绑定阶段直接解析失败,根本到不了你打算用DateTime.ParseExact()处理的步骤。
解决方案
方案1:自定义JSON转换器(推荐)
写一个自定义的JsonConverter,让它同时支持解析不带冒号的时区格式、带冒号的时区格式,以及无时区的格式。
自定义转换器代码
using System; using System.Text.Json; using System.Text.Json.Serialization; public class CustomDateTimeOffsetConverter : JsonConverter<DateTimeOffset?> { // 定义支持的三种格式 private const string FormatWithColonOffset = "yyyy-MM-ddTHH:mm:sszzz"; private const string FormatWithoutColonOffset = "yyyy-MM-ddTHH:mm:sszz"; private const string FormatWithoutOffset = "yyyy-MM-ddTHH:mm:ss"; public override DateTimeOffset? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.String) return null; var dateStr = reader.GetString()!; // 依次尝试解析三种格式 if (DateTimeOffset.TryParseExact(dateStr, FormatWithoutColonOffset, null, System.Globalization.DateTimeStyles.None, out var result)) return result; if (DateTimeOffset.TryParseExact(dateStr, FormatWithColonOffset, null, System.Globalization.DateTimeStyles.None, out result)) return result; if (DateTimeOffset.TryParseExact(dateStr, FormatWithoutOffset, null, System.Globalization.DateTimeStyles.None, out result)) return result; throw new JsonException($"无法解析日期字符串:{dateStr}"); } public override void Write(Utf8JsonWriter writer, DateTimeOffset? value, JsonSerializerOptions options) { if (value.HasValue) writer.WriteStringValue(value.Value.ToString(FormatWithColonOffset)); else writer.WriteNullValue(); } }
注册转换器
有两种注册方式,选其中一种即可:
方式A:给单个属性添加标记
在你的Project实体类的LastAnalysisDate属性上,加上转换器标记:
public class Project { public string Key { get; set; } public string Name { get; set; } [JsonConverter(typeof(CustomDateTimeOffsetConverter))] public DateTimeOffset? LastAnalysisDate { get; set; } // 其他属性... }
方式B:全局注册(对所有DateTimeOffset?生效)
在Program.cs(或旧版本的Startup.cs)中,配置全局JSON序列化选项:
builder.Services.AddControllers() .AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new CustomDateTimeOffsetConverter()); });
方案2:修改客户端传入的格式
如果能控制客户端的请求格式,把时区偏移部分加上冒号,比如将"2023-05-31T10:16:08-0400"改成"2023-05-31T10:16:08-04:00",这样默认的解析器就能直接处理,不需要额外代码。
额外说明
错误信息里的"The project field is required.",大概率是模型绑定的其他小问题——比如JSON属性名和模型属性名的大小写匹配问题(不过.NET默认支持大小写不敏感绑定),或者请求的JSON结构和Project类不匹配。解决完日期解析问题后,可以再排查这个问题。
内容的提问来源于stack exchange,提问作者wjhanna
相关产品推荐
相关产品推荐

