C#如何反序列化嵌套层数不固定的JSON数组

实现方案
固定层级的实体类无法适配嵌套层数不固定的JSON结构,通过自定义JSON转换器递归遍历所有嵌套的data字段,即可直接提取到最内层的HistoryData对象集合,无需逐层定义嵌套实体类。
方案1:使用Newtonsoft.Json(Json.NET)实现
- 简化实体类定义,给最外层data字段添加转换器注解:
public class BrowsingDataObject { public string api_msg { get; set; } public string api_code { get; set; } public string api_status { get; set; } // 直接指定最终解析目标类型,由转换器处理嵌套结构 [Newtonsoft.Json.JsonConverter(typeof(NestedDataArrayConverter<HistoryData>))] public HistoryData[] data { get; set; } } public class HistoryData { public string date_time { get; set; } public string url { get; set; } public string browser_source { get; set; } }
- 实现自定义递归转换器:
using Newtonsoft.Json; using Newtonsoft.Json.Linq; public class NestedDataArrayConverter<T> : JsonConverter { public override bool CanConvert(Type objectType) => objectType == typeof(T[]); public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JToken token = JToken.Load(reader); return ExtractInnerData(token).ToArray(); } private IEnumerable<T> ExtractInnerData(JToken token) { // 遍历数组元素 if (token.Type == JTokenType.Array) { foreach (var item in token.Children()) { foreach (var data in ExtractInnerData(item)) yield return data; } } // 处理对象,检查是否还有嵌套的data字段 else if (token.Type == JTokenType.Object) { var dataProp = token["data"]; if (dataProp != null) { foreach (var data in ExtractInnerData(dataProp)) yield return data; } else { // 无嵌套data,直接反序列化为目标对象 yield return token.ToObject<T>(); } } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException("仅用于反序列化,序列化功能未实现"); }
- 直接调用反序列化即可,适配任意嵌套层数:
var result = JsonConvert.DeserializeObject<BrowsingDataObject>(jsonResponse);
方案2:使用.NET内置System.Text.Json实现
- 实体类注解:
public class BrowsingDataObject { public string api_msg { get; set; } public string api_code { get; set; } public string api_status { get; set; } [System.Text.Json.Serialization.JsonConverter(typeof(NestedDataArrayConverter<HistoryData>))] public HistoryData[] data { get; set; } } public class HistoryData { public string date_time { get; set; } public string url { get; set; } public string browser_source { get; set; } }
- 自定义转换器实现:
using System.Text.Json; using System.Text.Json.Serialization; public class NestedDataArrayConverter<T> : JsonConverter<T[]> { public override T[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using JsonDocument doc = JsonDocument.ParseValue(ref reader); return ExtractInnerData(doc.RootElement, options).ToArray(); } private IEnumerable<T> ExtractInnerData(JsonElement element, JsonSerializerOptions options) { if (element.ValueKind == JsonValueKind.Array) { foreach (var item in element.EnumerateArray()) { foreach (var data in ExtractInnerData(item, options)) yield return data; } } else if (element.ValueKind == JsonValueKind.Object) { if (element.TryGetProperty("data", out var dataProp)) { foreach (var data in ExtractInnerData(dataProp, options)) yield return data; } else { yield return element.Deserialize<T>(options)!; } } } public override void Write(Utf8JsonWriter writer, T[] value, JsonSerializerOptions options) => throw new NotImplementedException("仅用于反序列化,序列化功能未实现"); }
内容的提问来源于stack exchange,提问作者jecs cor
相关产品推荐
相关产品推荐

