如何使用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
相关产品推荐
相关产品推荐

