C#使用System.Text.Json反序列化时如何忽略/解包外层对象节点
解决System.Text.Json反序列化时自动解包外层data节点的方案
你不需要修改现有employee模型类,以下两种方案都可以直接实现忽略外层data包裹节点、直接读取内部数组反序列化的需求:
方案1:临时解析取节点(实现最简单,无额外代码依赖)
先通过JsonDocument读取JSON结构,提取data节点对应的内容后再执行反序列化,适合单次、不需要复用逻辑的场景:
using System.Text.Json; // rawJson 为从Web服务接收到的原始JSON字符串 using JsonDocument jsonDoc = JsonDocument.Parse(rawJson); JsonElement dataSection = jsonDoc.RootElement.GetProperty("data"); // 配置大小写不敏感匹配,避免字段名大小写不一致导致反序列化失败 var serializeOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; List<employee> result = dataSection.Deserialize<List<employee>>(serializeOptions);
方案2:自定义JsonConverter(可复用,直接反序列化)
如果需要多次处理这类带data外层包裹的接口返回,可以自定义通用转换器,配置后不需要每次手动提取节点,还能兼容序列化时自动包装回data结构:
using System.Text.Json; using System.Text.Json.Serialization; public class DataWrapperConverter<T> : JsonConverter<List<T>> { // 反序列化逻辑:解包外层data节点 public override List<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using JsonDocument doc = JsonDocument.ParseValue(ref reader); return doc.RootElement.GetProperty("data").Deserialize<List<T>>(options); } // 序列化逻辑:自动包装为带data节点的结构,匹配接口要求 public override void Write(Utf8JsonWriter writer, List<T> value, JsonSerializerOptions options) { writer.WriteStartObject(); writer.WritePropertyName("data"); JsonSerializer.Serialize(writer, value, options); writer.WriteEndObject(); } }
使用时只需要把转换器加入序列化配置即可直接反序列化:
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, Converters = { new DataWrapperConverter<employee>() } }; // 直接传入原始JSON字符串即可得到目标结果,不需要额外处理节点 List<employee> employees = JsonSerializer.Deserialize<List<employee>>(rawJson, options);
注意事项
- 如果接口返回的
data节点名有变化,只需要修改转换器中GetProperty传入的节点名参数即可适配 - 开启
PropertyNameCaseInsensitive配置可以避免接口字段名、模型属性名大小写不一致导致的属性匹配失败问题
内容的提问来源于stack exchange,提问作者d00d
相关产品推荐
相关产品推荐

