You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)自定义转换器

  1. 编写自定义转换器类,处理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; }
    }
}
  1. 调用转换器完成反序列化:
var apiJson = "你的API返回的JSON字符串";
var serializerSettings = new JsonSerializerSettings();
serializerSettings.Converters.Add(new AnimalListConverter());
var animalList = JsonConvert.DeserializeObject<List<Animal>>(apiJson, serializerSettings);

方案二:使用System.Text.Json自定义转换器

  1. 编写适配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();
    }
}
  1. 执行反序列化操作:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 13:29:55