如何在System.Text.Json中为IEnumerable<T>使用自定义JsonConverter
问题描述
我使用自定义的System.Text.Json.JsonConverter来序列化/反序列化可表示为整数值的复杂枚举类型MyEnumType实例。当将转换器应用于单个属性时,JSON序列化符合预期,转换器功能正常:
[JsonConverter(typeof(MyEnumTypeConverter))] public MyEnumType Member { get; set; }
但将同一转换器应用于集合属性时却失败(原因是转换器类型与属性类型不匹配):
[JsonConverter(typeof(MyEnumTypeConverter))] public IEnumerable<MyEnumType> Members { get; set; }
我理解这种行为,但期望JSON序列化器能自动推断出应使用MyEnumType的自定义转换器来处理IEnumerable<MyEnumType>的元素。请问是否有办法配置JSON序列化,使其在处理集合元素时使用相同的JSON转换器?或者是否需要创建支持IEnumerable的自定义转换器版本?如果是后者,能否提供代码示例?
解决方案
方法1:全局注册转换器(推荐)
无需给集合属性单独标记转换器,直接在JsonSerializerOptions中注册MyEnumTypeConverter即可。序列化器会自动使用该转换器处理所有MyEnumType类型的对象,包括集合中的元素:
var options = new JsonSerializerOptions { Converters = { new MyEnumTypeConverter() } }; // 序列化示例 var json = JsonSerializer.Serialize(yourObjectInstance, options); // 反序列化示例 var targetObject = JsonSerializer.Deserialize<YourTargetType>(json, options);
采用这种方式后,所有MyEnumType实例(无论是单个属性还是集合元素)都会通过你的自定义转换器完成序列化/反序列化,不需要修改集合属性的特性标记。
方法2:创建集合专用转换器(仅当无法全局注册时使用)
如果必须通过属性标记指定转换器,需要编写一个针对IEnumerable<MyEnumType>的专用转换器,内部复用已有的MyEnumTypeConverter处理单个元素:
public class MyEnumTypeCollectionConverter : JsonConverter<IEnumerable<MyEnumType>> { private readonly MyEnumTypeConverter _elementConverter = new MyEnumTypeConverter(); public override IEnumerable<MyEnumType> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartArray) { throw new JsonException("JSON token is not an array."); } var elements = new List<MyEnumType>(); while (reader.Read()) { if (reader.TokenType == JsonTokenType.EndArray) break; // 复用单个元素转换器反序列化 var element = _elementConverter.Read(ref reader, typeof(MyEnumType), options); elements.Add(element); } return elements; } public override void Write(Utf8JsonWriter writer, IEnumerable<MyEnumType> value, JsonSerializerOptions options) { writer.WriteStartArray(); foreach (var item in value) { // 复用单个元素转换器序列化 _elementConverter.Write(writer, item, options); } writer.WriteEndArray(); } }
随后将该转换器标记在集合属性上即可:
[JsonConverter(typeof(MyEnumTypeCollectionConverter))] public IEnumerable<MyEnumType> Members { get; set; }
内容的提问来源于stack exchange,提问作者Tim Coulter
相关产品推荐
相关产品推荐

