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

如何在.NET Json多态序列化中兼容类重命名后的旧JSON文件?

解决.NET多态JSON序列化/反序列化的类重命名兼容问题

方法1:添加多组JsonDerivedType特性(最简单方案)

直接在基类上同时保留旧类型标识与新类的映射,配合新标识的映射,即可实现反序列化兼容旧JSON,序列化输出新标识的需求。

代码示例:

[JsonDerivedType(typeof(DerivedClass1), "derivedClass1")]
// 保留旧标识映射,兼容含"foo"的旧JSON
[JsonDerivedType(typeof(Bar), "foo")]
// 新标识用于序列化输出
[JsonDerivedType(typeof(Bar), "bar")]
public abstract class BaseClass
{
}

public class DerivedClass1 : BaseClass
{
}

public class Bar : BaseClass
{
}

反序列化时,JSON中的"foo"或"bar"都会被解析为Bar类;序列化Bar实例时,会自动使用最后一组JsonDerivedType指定的"bar"作为类型标识。

方法2:自定义JsonConverter(灵活适配复杂场景)

如果需要处理多个旧标识、或有其他自定义逻辑,可编写自定义转换器接管序列化/反序列化流程:

public class BaseClassConverter : JsonConverter<BaseClass>
{
    private readonly JsonConverter<BaseClass> _defaultConverter;

    public BaseClassConverter(JsonConverter<BaseClass> defaultConverter)
    {
        _defaultConverter = defaultConverter;
    }

    public override BaseClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;
        var discriminatorProp = options.TypeInfoResolverOptions.TypeDiscriminatorPropertyName;

        if (root.TryGetProperty(discriminatorProp, out var discriminator))
        {
            if (discriminator.GetString() == "foo")
            {
                // 将旧标识替换为新标识后再反序列化
                using var ms = new MemoryStream();
                using var writer = new Utf8JsonWriter(ms);
                
                writer.WriteStartObject();
                foreach (var prop in root.EnumerateObject())
                {
                    if (prop.Name == discriminatorProp)
                    {
                        writer.WriteString(prop.Name, "bar");
                    }
                    else
                    {
                        prop.WriteTo(writer);
                    }
                }
                writer.WriteEndObject();
                writer.Flush();
                
                ms.Position = 0;
                return JsonSerializer.Deserialize<BaseClass>(ms, options);
            }
        }

        return _defaultConverter.Read(ref reader, typeToConvert, options);
    }

    public override void Write(Utf8JsonWriter writer, BaseClass value, JsonSerializerOptions options)
    {
        // 序列化时直接使用默认逻辑,输出新标识"bar"
        _defaultConverter.Write(writer, value, options);
    }
}

注册转换器的代码:

var options = new JsonSerializerOptions();
var baseTypeInfo = options.TypeInfoResolver.GetTypeInfo(typeof(BaseClass), options) as JsonTypeInfo<BaseClass>;
var defaultConverter = baseTypeInfo.Converter as JsonConverter<BaseClass>;
options.Converters.Add(new BaseClassConverter(defaultConverter));

方法3:配置JsonPolymorphismOptions(.NET 7+适用)

若使用.NET 7及以上版本,可通过序列化配置添加旧标识映射,无需修改类特性:

var options = new JsonSerializerOptions();
var polyOptions = options.GetTypeInfo(typeof(BaseClass)).PolymorphismOptions;

// 添加旧标识到新类的映射
polyOptions.DerivedTypes.Add(new JsonDerivedType(typeof(Bar), "foo"));
// 确保新标识的映射存在(若类上已配置可省略)
polyOptions.DerivedTypes.Add(new JsonDerivedType(typeof(Bar), "bar"));

内容的提问来源于stack exchange,提问作者Rand Random

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 18:43:10