如何使用ServiceStack将带$type标识的JSON反序列化为指定类型的List
解决方案
你当前的JSON格式是Newtonsoft.Json(Json.NET)开启TypeNameHandling配置后生成的带类型标识的标准格式,无需自己做序列化/反序列化二次转换,直接配置对应参数即可直接反序列化。
核心错误说明
你最初代码执行失败的核心原因是反序列化目标类型填写错误:JSON根节点的类型是List<MyType>,而非MyType,同时没有开启类型识别配置。
具体实现步骤
1. 配置反序列化参数
开启TypeNameHandling以识别JSON中的$type字段,同时可自定义SerializationBinder做类型合法性校验,避免不安全的类型注入风险:
var deserializeSettings = new JsonSerializerSettings { // 开启类型识别,Auto级别会匹配JSON中携带的$type信息 TypeNameHandling = TypeNameHandling.Auto, // 自定义类型绑定器,只允许反序列化你指定的合法类型 SerializationBinder = new CustomTypeBinder() };
2. 实现自定义类型校验器
如果需要校验$type的合法性,实现ISerializationBinder接口限制允许反序列化的类型范围:
public class CustomTypeBinder : ISerializationBinder { // 定义允许反序列化的类型白名单 private readonly Dictionary<string, Type> _allowedTypes = new() { { "System.Collections.Generic.List<MyType>", typeof(List<MyType>) }, { "MyType", typeof(MyType) } }; public Type BindToType(string assemblyName, string typeName) { if (_allowedTypes.TryGetValue(typeName, out var validType)) { return validType; } throw new InvalidOperationException($"非法的反序列化类型:{typeName}"); } public void BindToName(Type serializedType, out string assemblyName, out string typeName) { assemblyName = null; typeName = _allowedTypes.FirstOrDefault(x => x.Value == serializedType).Key; } }
3. 直接反序列化得到目标对象
// 原生Newtonsoft.Json写法 var myList = JsonConvert.DeserializeObject<List<MyType>>(json, deserializeSettings); // 如果你用的是封装后的FromJson扩展方法,绝大多数实现都支持传入序列化配置参数 var myList = json.FromJson<List<MyType>>(deserializeSettings);
注意事项
- 不要直接使用
TypeNameHandling.All而不配置类型校验器,存在反序列化注入漏洞,恶意构造的JSON可以通过$type指定任意危险类型执行恶意代码。 - 如果你使用的是
System.Text.Json,原生不支持$type字段识别,需要自行实现JsonConverter做类型解析,更推荐使用Newtonsoft.Json处理这类带类型标识的JSON格式。
内容的提问来源于stack exchange,提问作者LorneCash
相关产品推荐
相关产品推荐

