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

如何反序列化含额外属性的JSON到NuGet类?兼容两大JSON库

解决方案:兼容双JSON库访问额外属性

前提回顾

无法修改NuGet提供的Base和Data类,JSON负载包含Data未定义的Value2属性,需同时兼容Newtonsoft.Json和System.Text.Json,且保留原有属性访问能力。


方案一:类型安全的派生类+扩展属性

通过创建派生类捕获额外属性,结合双库特性实现兼容。

1. 定义扩展类

创建继承自Data的扩展类,利用双库的扩展数据特性捕获未定义属性,并提供便捷访问:

public class ExtendedData : Data
{
    // 适配Newtonsoft.Json的扩展属性标记
    [Newtonsoft.Json.JsonExtensionData]
    // 适配System.Text.Json的扩展属性标记
    [System.Text.Json.Serialization.JsonExtensionData]
    public IDictionary<string, object> ExtraData { get; set; } = new Dictionary<string, object>();

    // 快速获取Value2的便捷属性
    public string Value2 => ExtraData.TryGetValue("Value2", out var val) ? val.ToString() : null;
}

// 派生Base类,替换Data属性为ExtendedData类型
public class ExtendedBase : Base
{
    public new ExtendedData Data { get; set; }
}

2. Newtonsoft.Json 适配

Newtonsoft原生支持派生类属性重写的类型替换,直接反序列化即可:

var settings = new Newtonsoft.Json.JsonSerializerSettings
{
    ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace
};

var extendedBase = Newtonsoft.Json.JsonConvert.DeserializeObject<ExtendedBase>(json, settings);

// 访问原有属性
var value1 = extendedBase.Data.Value1;
// 访问额外属性
var value2 = extendedBase.Data.Value2;

3. System.Text.Json 适配

System.Text.Json默认不支持属性重写的类型替换,需自定义转换器处理:

public class BaseConverter : System.Text.Json.Serialization.JsonConverter<ExtendedBase>
{
    public override ExtendedBase Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
    {
        var jsonElement = System.Text.Json.JsonElement.ParseValue(ref reader);
        var extendedBase = new ExtendedBase();

        // 反序列化基类原有属性(排除Data)
        var baseOptions = new System.Text.Json.JsonSerializerOptions(options);
        baseOptions.Converters.Remove(this);
        System.Text.Json.JsonSerializer.Deserialize(jsonElement.GetRawText(), extendedBase, baseOptions);

        // 单独反序列化Data为ExtendedData
        if (jsonElement.TryGetProperty("Data", out var dataElement))
        {
            extendedBase.Data = System.Text.Json.JsonSerializer.Deserialize<ExtendedData>(dataElement.GetRawText(), options);
        }

        return extendedBase;
    }

    public override void Write(System.Text.Json.Utf8JsonWriter writer, ExtendedBase value, System.Text.Json.JsonSerializerOptions options)
    {
        // 序列化时保留原Base结构,同时写入Value2
        System.Text.Json.JsonSerializer.Serialize(writer, (Base)value, options);
        writer.WriteString("Value2", value.Data.Value2);
    }
}

使用方式:

var options = new System.Text.Json.JsonSerializerOptions
{
    Converters = { new BaseConverter() },
    PropertyNameCaseInsensitive = true
};

var extendedBase = System.Text.Json.JsonSerializer.Deserialize<ExtendedBase>(json, options);

// 访问方式同Newtonsoft

方案二:动态对象映射(快速实现)

无需定义派生类,通过动态对象直接提取额外属性,适合快速开发场景(无类型安全)。

Newtonsoft.Json 实现

dynamic dynamicObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
var baseObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Base>(json);
string value2 = dynamicObj.Data.Value2;

// baseObj访问原有属性,value2访问额外属性

System.Text.Json 实现

using var jsonDoc = System.Text.Json.JsonDocument.Parse(json);
var baseObj = System.Text.Json.JsonSerializer.Deserialize<Base>(json);
string value2 = jsonDoc.RootElement.GetProperty("Data").GetProperty("Value2").GetString();

// baseObj访问原有属性,value2访问额外属性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 09:44:58