求助:JsonConvert.DeserializeObject获取Task List返回Null(API结构变更)
问题描述
我研究这个问题好几个小时了,还是没法完成Web API调用响应的反序列化。之前的代码运行正常,但API更新后接口结构变了——新增了Order层级,导致现有代码失效。我需要从API返回结果里提取Tasks列表来处理,Postman返回的API响应结构如下:
{"Version": 1,"Result": "Success","Data": {"Order": {"Oid": "f3a3afa9-ac2b-4914-b3cb-585c761f2dfb","Did": 265532,"Tasks": [{"Oid": "af82ce50-0587-4752-ba3b-d60dbfebe041","CreatedOn": "2023-05-19T02:24:55.437Z","ChangedOn": "2023-05-19T02:45:26.28Z","Description": "","Comment": "","IsStarted": false,"ScheduledOn": "2023-05-19T12:14:51.507","ProductionDeadline": "2023-05-21T16:00:00","ScheduledStart": "2023-05-19T11:56:00","ScheduledEnd": "2023-05-19T12:04:00","RealStart": "0001-01-01T00:00:00","RealEnd": "0001-01-01T00:00:00","OrderItemPartsCount": 27,"CalculatedSeconds": "120","IdleSeconds": "0","ScheduledSeconds": 480,"RealSeconds": 0,"PercentComplete": 0,"HasFinishedItems": false,"IsCustomTask": false,"AppointmentType": "OrderSpecificAppointment","Station": {"_Value": "Centurio","oid": "f7f3c5fe-49f0-4a9a-b366-29c4ab990fc7"},"MasterTask": {"_Value": "","oid": "179212f4-ff0e-465d-962c-51b7da711bb7"}},{"Oid": "72b6a0ba-cbc2-4f9b-9372-86805d40f7e3","CreatedOn": "2023-05-19T02:24:55.437Z","ChangedOn": "2023-05-19T02:25:28.37Z","Description": "","Comment": "","IsStarted": false,"ScheduledOn": "2023-05-19T11:54:55.437","ProductionDeadline": "2023-05-21T16:00:00","ScheduledStart": "2023-05-19T12:11:00","ScheduledEnd": "2023-05-19T13:10:00","RealStart": "0001-01-01T00:00:00","RealEnd": "0001-01-01T00:00:00","OrderItemPartsCount": 27,"CalculatedSeconds": "3540","IdleSeconds": "0","ScheduledSeconds": 3540,"RealSeconds": 0,"PercentComplete": 0,"HasFinishedItems": false,"IsCustomTask": false,"AppointmentType": "OrderSpecificAppointment","Station": {"_Value": "Twinmatic","oid": "d92a32c3-0763-49d7-a8eb-77ea68afa311"}}]}},"Details": ""}
旧版本的API响应里没有Order元素,求帮忙说明怎么把Tasks获取成List来做后续处理。
解决方案
方法1:强类型解析(定义匹配新结构的实体类)
这种方式更安全、易维护,适合长期项目。根据新的API响应结构创建对应实体类,直接反序列化后提取Tasks:
实体类定义(以C#为例)
// 最外层响应容器 public class ApiResponse { public int Version { get; set; } public string Result { get; set; } public ApiData Data { get; set; } public string Details { get; set; } } public class ApiData { public Order Order { get; set; } } public class Order { public string Oid { get; set; } public int Did { get; set; } public List<TaskItem> Tasks { get; set; } } // Task实体类,包含所有需要的字段 public class TaskItem { public string Oid { get; set; } public DateTime CreatedOn { get; set; } public DateTime ChangedOn { get; set; } public string Description { get; set; } public string Comment { get; set; } public bool IsStarted { get; set; } public DateTime ScheduledOn { get; set; } public DateTime ProductionDeadline { get; set; } public DateTime ScheduledStart { get; set; } public DateTime ScheduledEnd { get; set; } public DateTime RealStart { get; set; } public DateTime RealEnd { get; set; } public int OrderItemPartsCount { get; set; } public string CalculatedSeconds { get; set; } public string IdleSeconds { get; set; } public int ScheduledSeconds { get; set; } public int RealSeconds { get; set; } public int PercentComplete { get; set; } public bool HasFinishedItems { get; set; } public bool IsCustomTask { get; set; } public string AppointmentType { get; set; } public Station Station { get; set; } public MasterTask MasterTask { get; set; } } public class Station { public string _Value { get; set; } public string oid { get; set; } } public class MasterTask { public string _Value { get; set; } public string oid { get; set; } }
反序列化代码
使用Newtonsoft.Json(Json.NET)
string responseJson = "API返回的JSON字符串"; var apiResponse = JsonConvert.DeserializeObject<ApiResponse>(responseJson); List<TaskItem> tasks = apiResponse.Data.Order.Tasks;
使用System.Text.Json(.NET Core/.NET 5+内置)
string responseJson = "API返回的JSON字符串"; var apiResponse = JsonSerializer.Deserialize<ApiResponse>(responseJson); List<TaskItem> tasks = apiResponse.Data.Order.Tasks;
方法2:动态解析(无需定义实体类)
如果只是临时提取数据,不想定义大量实体类,可以用动态类型直接定位Tasks:
使用Newtonsoft.Json的JObject
string responseJson = "API返回的JSON字符串"; var jObj = JObject.Parse(responseJson); // 直接提取Tasks列表 List<JObject> tasks = jObj["Data"]["Order"]["Tasks"].ToObject<List<JObject>>();
使用System.Text.Json的JsonDocument
string responseJson = "API返回的JSON字符串"; using var doc = JsonDocument.Parse(responseJson); var tasksElement = doc.RootElement.GetProperty("Data").GetProperty("Order").GetProperty("Tasks"); // 转成列表或按需遍历提取属性 List<JsonElement> tasks = tasksElement.EnumerateArray().ToList();
核心修改点
对比旧代码,原来的Data节点直接包含Tasks,现在需要多走一层Order节点——也就是从Data.Tasks改成Data.Order.Tasks,这是让代码恢复正常的关键。
内容的提问来源于stack exchange,提问作者Buda56
相关产品推荐
相关产品推荐

