如何用Newtonsoft反序列化含单个对象与对象列表的JSON?
嘿,我来帮你搞定这个JSON反序列化的问题!你想的方向完全没错——从JObject里提取对应JToken再转成目标.NET类型,就是处理这种混合结构JSON的常用方法。下面结合你的代码,一步步给你讲清楚怎么实现:
解决思路与具体实现
首先得先明确你的JSON结构(这是关键前提),因为不同的结构对应不同的提取方式。先假设两种最常见的场景,再给出代码:
先搞清楚你的JSON结构
举两个典型的混合结构场景:
场景1:Recipe->data下同时包含单个对象和列表字段
比如你的JSON长这样:
{ "Recipe": { "data": { "CurrentRecipe": { "Id": 1, "Name": "番茄炒蛋" }, "RelatedRecipes": [ { "Id": 2, "Name": "番茄鸡蛋汤" }, { "Id": 3, "Name": "青椒炒蛋" } ] } } }
对应的.NET实体类你应该已经定义好了,比如:
public class Recipe { public int Id { get; set; } public string Name { get; set; } }
场景2:data本身是单个对象,列表是同级字段
比如JSON是这种结构:
{ "Recipe": { "data": { "Id": 1, "Name": "番茄炒蛋" }, "RelatedRecipes": [ { "Id": 2, "Name": "番茄鸡蛋汤" }, { "Id": 3, "Name": "青椒炒蛋" } ] } }
针对性的反序列化代码
处理场景1的代码
// 你的初始解析代码没问题 JObject recipePageObject = JObject.Parse(await resp.Content.ReadAsStringAsync()); // 提取单个对象的JToken并转成.NET类型 JToken singleRecipeToken = recipePageObject["Recipe"]["data"]["CurrentRecipe"]; Recipe singleRecipe = singleRecipeToken.ToObject<Recipe>(); // 提取列表的JToken并转成List<Recipe> JToken recipeListToken = recipePageObject["Recipe"]["data"]["RelatedRecipes"]; List<Recipe> recipeList = recipeListToken.ToObject<List<Recipe>>();
处理场景2的代码
JObject recipePageObject = JObject.Parse(await resp.Content.ReadAsStringAsync()); // 直接把data节点转成单个Recipe对象 Recipe singleRecipe = recipePageObject["Recipe"]["data"].ToObject<Recipe>(); // 提取同级的列表字段转成List<Recipe> List<Recipe> recipeList = recipePageObject["Recipe"]["RelatedRecipes"].ToObject<List<Recipe>>();
你当前代码的小问题
你用了.Children(),这个方法会返回当前JToken的所有直接子节点。如果data本身是一个对象(不是数组),.Children()返回的是它的所有属性节点,这显然不是你想要的结果。直接针对目标字段提取JToken,再用.ToObject<T>()转换就好,不需要用.Children()。
额外的小技巧:空值检查
为了避免空引用异常,建议加个简单的空值判断:
if (recipePageObject["Recipe"]?["data"] is JToken dataToken && dataToken != null) { // 在这里处理单个对象或列表的转换 }
这样就能安全又准确地完成混合结构的JSON反序列化啦!
内容的提问来源于stack exchange,提问作者Samuel Mungy
相关产品推荐
相关产品推荐

