ASP.NET Core 6.0如何实现DateOnlyJsonConverter解决DateOnly序列化报错
问题根因
- 你当前实现的自定义转换器仅支持解析
yyyy-MM-dd格式的字符串入参,无法兼容请求中传入的{year, month, day, dayOfWeek}结构的对象格式日期 - 当JSON节点为对象类型时,
reader.Value取值为null,直接强转string后调用ParseExact就会抛出ArgumentNullException - 仅在属性上标注
[JsonConverter]时,构造函数参数绑定阶段不会识别该特性,会导致部分场景反序列化失败
完整实现方案
1. 修正后的DateOnly自定义转换器
该实现同时兼容字符串格式、对象格式两种入参,自带空值处理和异常兜底:
using System.Globalization; using Newtonsoft.Json; using Newtonsoft.Json.Linq; public class DateOnlyJsonConverter : JsonConverter<DateOnly> { private const string StandardDateFormat = "yyyy-MM-dd"; public override void WriteJson(JsonWriter writer, DateOnly value, JsonSerializer serializer) { // 序列化统一输出为yyyy-MM-dd格式字符串,避免返回嵌套对象结构 writer.WriteValue(value.ToString(StandardDateFormat, CultureInfo.InvariantCulture)); } public override DateOnly ReadJson(JsonReader reader, Type objectType, DateOnly existingValue, bool hasExistingValue, JsonSerializer serializer) { // 处理空值场景 if (reader.TokenType == JsonToken.Null) return default; // 处理yyyy-MM-dd格式字符串入参 if (reader.TokenType == JsonToken.String) { var rawValue = reader.Value?.ToString(); if (DateOnly.TryParseExact(rawValue, StandardDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsedDate)) return parsedDate; // 兜底兼容其他合法日期字符串格式 if (DateOnly.TryParse(rawValue, CultureInfo.InvariantCulture, DateTimeStyles.None, out var fallbackDate)) return fallbackDate; } // 处理{year,month,day}结构的对象入参 if (reader.TokenType == JsonToken.StartObject) { var dateObj = JObject.Load(reader); var year = dateObj.Value<int>("year"); var month = dateObj.Value<int>("month"); var day = dateObj.Value<int>("day"); return new DateOnly(year, month, day); } throw new JsonSerializationException($"无法将当前Token类型[{reader.TokenType}]转换为DateOnly"); } }
2. 全局注册转换器
修改Program.cs中的Newtonsoft.Json配置,全局注册自定义转换器,覆盖构造函数绑定、属性序列化全场景,不需要在每个DateOnly属性上重复标注[JsonConverter]:
builder.Services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new DateOnlyJsonConverter()); });
验证说明
- 反序列化支持两种入参:
"postDate": "2020-10-10"和你当前使用的嵌套对象结构都可以正常转换为DateOnly类型 - 序列化输出统一为
"postDate": "2020-10-10"格式,符合接口传输的通用规范 - 如果需要支持可空类型
DateOnly?,参考上述逻辑额外实现JsonConverter<DateOnly?>即可,空值场景直接返回null
内容的提问来源于stack exchange,提问作者maxfromgermany
相关产品推荐
相关产品推荐

