使用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
相关产品推荐
相关产品推荐

