.NET 7 Web API中DateOnly类型解析失败问题求助
问题分析
你遇到的The JSON value could not be converted to DateOnly错误,核心原因是:你传入的startDate/endDate是嵌套对象结构(包含year/month/day等属性),但你使用的DateOnlyTimeOnly.AspNet包默认只支持解析ISO日期字符串格式(比如"2023-05-29"),因此无法识别这种对象格式的日期数据。
解决方案
以下三种方案任选其一即可:
方案一:修改请求负载为ISO日期字符串(最简单)
直接将请求中的日期字段改为标准ISO字符串格式,不需要修改后端代码,包的转换器就能自动解析:
[ { "startDate": "2023-05-29", "name": "string", "endDate": "2023-11-01" } ]
方案二:自定义JSON转换器处理对象格式的DateOnly
如果无法修改请求格式,可编写自定义转换器来解析这种嵌套对象结构的日期:
- 创建自定义转换器类:
public class DateOnlyObjectConverter : JsonConverter<DateOnly> { public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) throw new JsonException("DateOnly字段应为对象格式"); int year = 0, month = 0, day = 0; while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndObject) break; if (reader.TokenType != JsonTokenType.PropertyName) continue; var propName = reader.GetString(); reader.Read(); switch (propName.ToLower()) { case "year": year = reader.GetInt32(); break; case "month": month = reader.GetInt32(); break; case "day": day = reader.GetInt32(); break; // dayOfWeek无需处理,DateOnly会自动计算 } } return new DateOnly(year, month, day); } public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WriteNumber("year", value.Year); writer.WriteNumber("month", value.Month); writer.WriteNumber("day", value.Day); writer.WriteNumber("dayOfWeek", (int)value.DayOfWeek); writer.WriteEndObject(); } }
- 在
Program.cs中注册转换器:
builder.Services.AddControllers() .AddJsonOptions(options => { // 移除包自带的DateOnly转换器(避免冲突) var defaultConverter = options.JsonSerializerOptions.Converters .FirstOrDefault(c => c is JsonConverter<DateOnly>); if (defaultConverter != null) options.JsonSerializerOptions.Converters.Remove(defaultConverter); // 添加自定义转换器 options.JsonSerializerOptions.Converters.Add(new DateOnlyObjectConverter()); });
方案三:使用DTO中间对象做数据映射
创建与请求格式匹配的DTO类,接收请求后手动映射为DateOnly类型:
- 定义DTO类:
public class DataDto { public DateDto StartDate { get; set; } public string Name { get; set; } public DateDto EndDate { get; set; } } public class DateDto { public int Year { get; set; } public int Month { get; set; } public int Day { get; set; } public int DayOfWeek { get; set; } }
- 修改接口方法:
[HttpPost("Save")] public async Task<IActionResult> Save([FromBody] IEnumerable<DataDto> dataDtos) { // 将DTO映射为业务实体 var dataList = dataDtos.Select(dto => new Data { StartDate = new DateOnly(dto.StartDate.Year, dto.StartDate.Month, dto.StartDate.Day), Name = dto.Name, EndDate = new DateOnly(dto.EndDate.Year, dto.EndDate.Month, dto.EndDate.Day) }).ToList(); // 业务逻辑处理... return Ok(); }
内容的提问来源于stack exchange,提问作者lolo xoxo
相关产品推荐
相关产品推荐

