如何为类中数组/列表的内部类型使用JsonConverterAttribute特性
给集合元素应用Json转换器:仅靠类装饰器实现的方案
嘿,我完全get到你的需求了——不想为IList<DateTime>这类泛型集合单独写转换器,也不想全局注册转换器,只希望通过给目标类加特性,就能让集合里的每个元素自动用上指定的Json转换器对吧?
刚好Newtonsoft.Json(也就是Json.NET)提供了完美的解决方案,不用绕弯路,直接用[JsonProperty]特性的ItemConverterType属性就能搞定。下面给你一步步演示:
步骤1:编写针对元素类型的转换器
先写一个针对你要处理的元素类型的转换器,比如针对DateTime的自定义格式转换器:
public class CustomDateTimeConverter : JsonConverter<DateTime> { // 自定义日期格式 private const string DateFormat = "yyyy-MM-dd"; public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer) { return DateTime.ParseExact(reader.Value.ToString(), DateFormat, CultureInfo.InvariantCulture); } public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer) { writer.WriteValue(value.ToString(DateFormat)); } }
步骤2:在目标类的集合属性上添加特性
接下来,直接在你的类的集合属性上标记[JsonProperty],并指定ItemConverterType为刚才写的转换器:
public class EventTracking { // 关键:用ItemConverterType指定集合元素要使用的转换器 [JsonProperty(ItemConverterType = typeof(CustomDateTimeConverter))] public List<DateTime> RecordedDates { get; set; } public string EventName { get; set; } }
验证效果
现在不管是序列化还是反序列化,这个集合里的每个DateTime元素都会自动应用CustomDateTimeConverter:
// 序列化示例 var tracking = new EventTracking { EventName = "2024年度会议", RecordedDates = new List<DateTime> { new(2024, 3, 15), new(2024, 4, 20) } }; var json = JsonConvert.SerializeObject(tracking); // 输出结果:{"EventName":"2024年度会议","RecordedDates":["2024-03-15","2024-04-20"]} // 反序列化示例 var deserialized = JsonConvert.DeserializeObject<EventTracking>(json); // deserialized.RecordedDates里的元素会被正确解析为DateTime类型
方案优势
- 不用为
List<DateTime>、DateTime[]这类集合类型单独编写转换器,只需要实现元素类型的转换器即可 - 不需要在
JsonSerializerSettings里全局注册转换器,特性只作用于当前属性,精准控制作用范围 - 完全通过目标类的装饰器实现,完全符合你的需求
如果是用System.Text.Json的话,目前没有直接的ItemConverterType属性,但可以通过编写一个包装集合的转换器来实现类似效果,不过Newtonsoft.Json的方案更直接简洁,完全匹配你的需求。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

