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

使用JsonConverter属性格式化DateTime列表报错,寻求解决方案

解决思路:为List<DateTime>字段应用自定义日期格式转换器

这个问题的核心原因很明确:IsoDateTimeConverter是专门为单个DateTime或DateTimeOffset对象设计的转换器,它无法直接处理集合类型(比如List<DateTime>)。当你把这个转换器标记在集合字段上时,Json.NET会尝试将整个列表当作单个日期值来转换,这就导致了错误提示里的类型不匹配问题。

下面给你几个可行的解决思路,你可以根据自己的场景选择:

方案一:自定义支持集合的日期转换器

创建一个专门针对List<DateTime>的转换器,逐个处理集合中的每个日期元素:

using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public class DateListConverter : JsonConverter<List<DateTime>>
{
    private readonly string _dateFormat;

    // 默认使用yyyy-MM-dd格式
    public DateListConverter() : this("yyyy-MM-dd")
    {
    }

    // 允许自定义日期格式
    public DateListConverter(string dateFormat)
    {
        _dateFormat = dateFormat ?? throw new ArgumentNullException(nameof(dateFormat));
    }

    public override void WriteJson(JsonWriter writer, List<DateTime> value, JsonSerializer serializer)
    {
        if (value == null)
        {
            writer.WriteNull();
            return;
        }

        writer.WriteStartArray();
        foreach (var date in value)
        {
            writer.WriteValue(date.ToString(_dateFormat, CultureInfo.InvariantCulture));
        }
        writer.WriteEndArray();
    }

    public override List<DateTime> ReadJson(JsonReader reader, Type objectType, List<DateTime> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
        {
            return null;
        }

        var dateList = new List<DateTime>();
        if (reader.TokenType != JsonToken.StartArray)
        {
            throw new JsonSerializationException($"Expected start of array, got {reader.TokenType}");
        }

        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.EndArray)
            {
                break;
            }

            if (reader.TokenType == JsonToken.String)
            {
                if (DateTime.TryParseExact((string)reader.Value, _dateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsedDate))
                {
                    dateList.Add(parsedDate);
                }
                else
                {
                    // 可选:处理日期解析失败的情况,比如抛出异常或添加默认值
                    throw new JsonSerializationException($"Cannot parse '{reader.Value}' using format '{_dateFormat}'");
                }
            }
            else
            {
                throw new JsonSerializationException($"Expected string date value, got {reader.TokenType}");
            }
        }

        return dateList;
    }
}

然后在你的类中使用这个转换器:

public class A
{
    [JsonConverter(typeof(DateListConverter))]
    public List<DateTime> Example { get; set; }
}

这个方案的优势是精准控制单个字段的序列化/反序列化逻辑,适合只有部分集合需要特殊日期格式的场景。

方案二:全局配置日期格式

如果你的项目中所有DateTime类型(包括集合中的元素)都需要统一使用yyyy-MM-dd格式,可以直接在JsonSerializerSettings中全局配置,不需要自定义转换器:

var settings = new JsonSerializerSettings
{
    DateFormatString = "yyyy-MM-dd",
    Culture = CultureInfo.InvariantCulture
};

// 序列化示例
var aInstance = new A { Example = new List<DateTime> { DateTime.Now, DateTime.UtcNow } };
var json = JsonConvert.SerializeObject(aInstance, settings);

// 反序列化示例
var deserializedA = JsonConvert.DeserializeObject<A>(json, settings);

这个方案最简单,适合全局统一日期格式的场景,避免了重复标记属性的麻烦。

方案三:序列化时临时指定转换器

如果只是偶尔需要对某个集合应用特殊格式,可以在序列化/反序列化时直接传入转换器,不需要修改类的属性标记:

var converter = new DateListConverter();
var json = JsonConvert.SerializeObject(aInstance, converter);
var deserializedA = JsonConvert.DeserializeObject<A>(json, converter);

这个方案灵活,适合临时处理特定序列化场景的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:45:32