You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 14:54:19