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

无法访问类型时,如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:40:56