无法访问类型时,如何在System.Text.Json中自定义多态类型鉴别器的名称与值?
在System.Text.Json中自定义多态类型鉴别器的属性名与值(无需修改类型)
可以通过配置序列化器实现需求,无需修改目标类型本身,以下分.NET版本给出具体方案:
.NET 7及以上版本(推荐)
.NET 7开始,System.Text.Json内置了修改类型鉴别器属性名的API,同时支持通过配置添加类型与自定义鉴别器值的映射。
实现代码:
public class Person { public string Name { get; set; } } // 配置序列化选项 var options = new JsonSerializerOptions { WriteIndented = true, // 可选,格式化输出便于查看 TypeInfoResolver = new DefaultJsonTypeInfoResolver { Modifiers = { typeInfo => { // 针对多态基类(此处以Person为例,若有父类可替换为父类类型) if (typeInfo.Type == typeof(Person)) { typeInfo.PolymorphismOptions = new JsonPolymorphismOptions { TypeDiscriminatorPropertyName = "__type", // 修改鉴别器属性名 IgnoreUnrecognizedTypeDiscriminators = true, DerivedTypes = { new JsonDerivedType(typeof(Person), "P"), // 映射类型与自定义鉴别器值 // 可添加更多派生类,如 new JsonDerivedType(typeof(Student), "S") } }; } } } } }; // 序列化示例 var people = new Person[] { new Person { Name = "AbcPerson" } }; var serialized = JsonSerializer.Serialize(people, options); Console.WriteLine(serialized); // 反序列化示例 var deserialized = JsonSerializer.Deserialize<Person[]>(serialized, options);
输出结果:
[ { "__type": "P", "Name": "AbcPerson" } ]
.NET 6及更早版本
此版本无内置修改鉴别器属性名的API,需自定义JsonConverter手动处理类型鉴别器的读写逻辑。
自定义转换器代码:
public class PolymorphicConverter<TBase> : JsonConverter<TBase> { private readonly Dictionary<string, Type> _discriminatorToTypeMap; private readonly Dictionary<Type, string> _typeToDiscriminatorMap; public PolymorphicConverter(Dictionary<Type, string> discriminatorMappings) { _discriminatorToTypeMap = discriminatorMappings.ToDictionary(kvp => kvp.Value, kvp => kvp.Key); _typeToDiscriminatorMap = discriminatorMappings; } public override TBase Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.StartObject) throw new JsonException("JSON必须以对象开头"); using var doc = JsonDocument.ParseValue(ref reader); var root = doc.RootElement; if (!root.TryGetProperty("__type", out var discriminatorElement) || string.IsNullOrEmpty(discriminatorElement.GetString())) throw new JsonException("缺少有效__type属性"); var discriminator = discriminatorElement.GetString(); if (!_discriminatorToTypeMap.TryGetValue(discriminator, out var targetType)) throw new JsonException($"未知类型鉴别器:{discriminator}"); return (TBase)JsonSerializer.Deserialize(root.GetRawText(), targetType, options); } public override void Write(Utf8JsonWriter writer, TBase value, JsonSerializerOptions options) { var valueType = value.GetType(); if (!_typeToDiscriminatorMap.TryGetValue(valueType, out var discriminator)) throw new JsonException($"不支持的类型:{valueType.Name}"); writer.WriteStartObject(); writer.WriteString("__type", discriminator); // 序列化对象其他属性 var element = JsonSerializer.SerializeToElement(value, options); foreach (var prop in element.EnumerateObject()) { if (prop.Name != "__type") prop.WriteTo(writer); } writer.WriteEndObject(); } }
使用示例:
public class Person { public string Name { get; set; } } // 配置类型与鉴别器的映射 var discriminatorMappings = new Dictionary<Type, string> { { typeof(Person), "P" } }; // 配置序列化选项 var options = new JsonSerializerOptions { WriteIndented = true, Converters = { new PolymorphicConverter<Person>(discriminatorMappings) } }; // 序列化与反序列化 var people = new Person[] { new Person { Name = "AbcPerson" } }; var serialized = JsonSerializer.Serialize(people, options); Console.WriteLine(serialized); var deserialized = JsonSerializer.Deserialize<Person[]>(serialized, options);
输出结果:
[ { "__type": "P", "Name": "AbcPerson" } ]
内容的提问来源于stack exchange,提问作者Yola
相关产品推荐
相关产品推荐

