C#中如何将含子列表的JSON反序列化为多个Animal对象
问题描述
我从API获取到如下格式的JSON数据:
{ "name": "Animals", "className": "Mammals", "speciesList": [ { "species": "Panthera leo", "subspecies": "leo" }, { "species": "Equus quagga", "subspecies": "quagga" } ] }
我希望将其直接反序列化为多个如下定义的Animal类对象:
public class Animal { public string name {get; set;} public string className {get; set;} public string species {get; set;} public string subspecies {get; set;} }
最终要得到2个实例:
Animal("Animals", "Mammals", "Panthera leo", "leo") Animal("Animals", "Mammals", "Equus quagga", "quagga")
我知道可以通过先提取数据再转换的方式实现,但想了解是否有直接反序列化的方法。
直接反序列化的实现方案
可以通过自定义反序列化逻辑一步完成转换,下面以.NET生态中两种主流JSON库为例说明:
方案一:使用Newtonsoft.Json(Json.NET)自定义转换器
- 编写自定义转换器类,处理JSON到
List<Animal>的转换逻辑:
public class AnimalListConverter : JsonConverter<List<Animal>> { public override List<Animal> ReadJson(JsonReader reader, Type objectType, List<Animal> existingValue, bool hasExistingValue, JsonSerializer serializer) { var jsonObj = JObject.Load(reader); // 提取顶层公共字段 var baseName = jsonObj["name"].ToString(); var baseClassName = jsonObj["className"].ToString(); // 解析物种列表 var speciesList = jsonObj["speciesList"].ToObject<List<SpeciesItem>>(); // 生成目标Animal实例列表 return speciesList.Select(s => new Animal { name = baseName, className = baseClassName, species = s.species, subspecies = s.subspecies }).ToList(); } public override void WriteJson(JsonWriter writer, List<Animal> value, JsonSerializer serializer) { // 若不需要将Animal列表序列化回原JSON格式,可直接抛出异常或留空 throw new NotImplementedException(); } // 临时类用于解析speciesList中的单项数据 private class SpeciesItem { public string species { get; set; } public string subspecies { get; set; } } }
- 调用转换器完成反序列化:
var apiJson = "你的API返回的JSON字符串"; var serializerSettings = new JsonSerializerSettings(); serializerSettings.Converters.Add(new AnimalListConverter()); var animalList = JsonConvert.DeserializeObject<List<Animal>>(apiJson, serializerSettings);
方案二:使用System.Text.Json自定义转换器
- 编写适配System.Text.Json的转换器:
public class AnimalListSystemTextConverter : JsonConverter<List<Animal>> { public override List<Animal> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using var jsonDoc = JsonDocument.ParseValue(ref reader); var rootElement = jsonDoc.RootElement; // 读取顶层公共字段 var baseName = rootElement.GetProperty("name").GetString(); var baseClassName = rootElement.GetProperty("className").GetString(); // 遍历物种列表 var speciesElements = rootElement.GetProperty("speciesList").EnumerateArray(); var animalList = new List<Animal>(); foreach (var speciesElement in speciesElements) { animalList.Add(new Animal { name = baseName, className = baseClassName, species = speciesElement.GetProperty("species").GetString(), subspecies = speciesElement.GetProperty("subspecies").GetString() }); } return animalList; } public override void Write(Utf8JsonWriter writer, List<Animal> value, JsonSerializerOptions options) { throw new NotImplementedException(); } }
- 执行反序列化操作:
var apiJson = "你的API返回的JSON字符串"; var serializerOptions = new JsonSerializerOptions(); serializerOptions.Converters.Add(new AnimalListSystemTextConverter()); var animalList = JsonSerializer.Deserialize<List<Animal>>(apiJson, serializerOptions);
核心逻辑
两种方案的本质都是在反序列化过程中,先读取JSON顶层的name和className公共字段,再遍历speciesList数组,为每个物种项填充公共字段后生成Animal实例,从而一步完成从原JSON结构到目标对象列表的转换。
内容的提问来源于stack exchange,提问作者Ces
相关产品推荐
相关产品推荐

