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

如何使用Newtonsoft.Json解析含泛型列表的JSON至原对象?

解决Newtonsoft.Json反序列化带泛型对象列表的问题

看起来你遇到的核心问题是:序列化时泛型类型的信息没有被保留在JSON里,导致反序列化时Newtonsoft不知道该把Value字段映射回哪种具体的泛型类型。结合你给出的JSON结构,我给你两种常用的解决方案:


方案一:序列化时保留类型信息(最简单直接)

Newtonsoft.Json提供了TypeNameHandling配置,可以在JSON中嵌入类型元数据,这样反序列化时就能精准识别泛型类型。

步骤1:配置序列化设置

假设你的容器类和泛型类结构如下,序列化时添加TypeNameHandling配置:

public class MyObjectContainer
{
    public List<Wrapper<object>> List { get; set; }
}

public class Wrapper<T>
{
    public T Value { get; set; }
}

// 序列化示例代码
var container = new MyObjectContainer
{
    List = new List<Wrapper<object>>
    {
        new Wrapper<object> { Value = new { StrValue = "bbb" } },
        new Wrapper<object> { Value = new { DoubleValue = 5.43 } }
    }
};

var serializeSettings = new JsonSerializerSettings
{
    // Auto会在需要时自动添加类型信息,All则强制所有类型都附加
    TypeNameHandling = TypeNameHandling.Auto,
    Formatting = Formatting.Indented
};

string json = JsonConvert.SerializeObject(container, serializeSettings);

此时生成的JSON会包含$type字段,类似这样:

{
  "List": [
    {
      "$type": "YourNamespace.Wrapper`1[[System.Object, mscorlib]], YourAssembly",
      "Value": {
        "$type": "<>f__AnonymousType0`1[[System.String, mscorlib]], YourAssembly",
        "StrValue": "bbb"
      }
    },
    {
      "$type": "YourNamespace.Wrapper`1[[System.Object, mscorlib]], YourAssembly",
      "Value": {
        "$type": "<>f__AnonymousType1`1[[System.Double, mscorlib]], YourAssembly",
        "DoubleValue": 5.43
      }
    }
  ]
}

步骤2:反序列化时复用相同配置

反序列化时必须使用同样的TypeNameHandling设置,才能正确解析类型信息:

var deserializeSettings = new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Auto
};

var deserializedContainer = JsonConvert.DeserializeObject<MyObjectContainer>(json, deserializeSettings);

⚠️ 注意:这种方法存在安全风险,如果你的程序需要反序列化来自不可信来源的JSON,不建议使用TypeNameHandling.All,避免被注入恶意类型。


方案二:自定义JSON转换器(无需类型元数据)

如果你不想在JSON中暴露类型信息,可以写一个自定义转换器,通过判断Value字段的内容来决定反序列化的具体类型。

步骤1:定义基类和泛型子类(可选但更清晰)

如果你的泛型对象有共同基类,先定义基类来统一处理:

public abstract class ValueBase { }

public class StringValue : ValueBase
{
    public string StrValue { get; set; }
}

public class DoubleValue : ValueBase
{
    public double DoubleValue { get; set; }
}

public class Wrapper<T> where T : ValueBase
{
    public T Value { get; set; }
}

public class MyContainer
{
    public List<Wrapper<ValueBase>> List { get; set; }
}

步骤2:实现自定义转换器

public class WrapperConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // 指定转换器处理Wrapper<ValueBase>类型
        return objectType == typeof(Wrapper<ValueBase>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
        var valueToken = jObject["Value"];

        // 根据Value里的字段判断具体类型
        if (valueToken["StrValue"] != null)
        {
            var stringValue = valueToken.ToObject<StringValue>(serializer);
            return new Wrapper<StringValue> { Value = stringValue };
        }
        else if (valueToken["DoubleValue"] != null)
        {
            var doubleValue = valueToken.ToObject<DoubleValue>(serializer);
            return new Wrapper<DoubleValue> { Value = doubleValue };
        }

        throw new JsonSerializationException("无法识别的Value类型");
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // 序列化时直接使用默认逻辑即可
        serializer.Serialize(writer, value);
    }
}

步骤3:使用转换器反序列化

var settings = new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new WrapperConverter() }
};

var deserializedContainer = JsonConvert.DeserializeObject<MyContainer>(yourJsonString, settings);

这种方法更灵活,也不需要在JSON中添加额外类型信息,适合对JSON格式有严格要求的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:21:47