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

使用NewtonsoftJson在控制器中读取原始JSON DateTime值并移除时区

解决DateTime DTO属性移除时区信息的问题

问题核心

你遇到的问题是Newtonsoft.Json默认会自动将带时区的日期字符串转换为本地时区的DateTime对象,导致自定义转换器的ReadJson方法中无法获取原始的JSON字符串值。下面提供两种可行的解决方案:


方案1:自定义转换器(精准控制)

直接在转换器中读取原始的日期字符串,截断时区部分后再解析为DateTime:

public class DateTimeWithoutTimeZoneConverter : DateTimeConverterBase
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime) || objectType == typeof(DateTime?);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // 仅处理字符串类型的日期节点
        if (reader.TokenType != JsonToken.String)
        {
            return objectType == typeof(DateTime?) ? null : DateTime.MinValue;
        }

        var rawDateStr = reader.Value.ToString();
        // 定位时区分隔符(+/-),截断字符串
        var zoneSeparatorIndex = rawDateStr.IndexOfAny(new[] { '+', '-' });
        if (zoneSeparatorIndex > 0)
        {
            rawDateStr = rawDateStr.Substring(0, zoneSeparatorIndex);
        }

        // 解析为DateTime,指定Kind为Unspecified(避免自动时区转换)
        if (DateTime.TryParse(rawDateStr, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result))
        {
            return objectType == typeof(DateTime?) ? (object?)result : result;
        }

        // 解析失败返回默认值(可根据需求抛出异常)
        return objectType == typeof(DateTime?) ? null : DateTime.MinValue;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // 序列化时输出不带时区的标准格式
        if (value is DateTime date)
        {
            writer.WriteValue(date.ToString("yyyy-MM-ddTHH:mm:ss.fff", CultureInfo.InvariantCulture));
        }
        else if (value is DateTime? nullableDate && nullableDate.HasValue)
        {
            writer.WriteValue(nullableDate.Value.ToString("yyyy-MM-ddTHH:mm:ss.fff", CultureInfo.InvariantCulture));
        }
        else
        {
            writer.WriteNull();
        }
    }
}

注册方式保持你之前的代码即可:

services.AddControllers()
    .AddNewtonsoftJson(options => 
        options.SerializerSettings.Converters.Add(new DateTimeWithoutTimeZoneConverter()))

原理说明

通过检查JsonReader.TokenType是否为JsonToken.String,直接读取原始的日期字符串,而非已经被Newtonsoft转换后的DateTime对象,这样就能手动截断时区部分,得到你需要的纯日期时间值。


方案2:全局配置(快速生效)

如果不需要精准控制单个属性,可直接通过Newtonsoft的全局配置忽略时区:

services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        // 反序列化时忽略时区,将日期解析为Unspecified类型的DateTime
        options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Unspecified;
        // 序列化时同样输出不带时区的格式
        options.SerializerSettings.DateFormatString = "yyyy-MM-ddTHH:mm:ss.fff";
    });

优缺点

  • 优点:无需编写自定义转换器,配置简单,全局生效
  • 缺点:所有DateTime类型的序列化/反序列化都会忽略时区,无法针对单个属性做特殊处理

内容的提问来源于stack exchange,提问作者ilyazakharov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 01:20:26