使用Refit反序列化Digicert API响应至实体类失败问题排查
我正在使用Refit + HttpClient Factory对接Digicert Automation API。当接口方法声明返回string类型(Task<string> GetAgentList([Body] GetAgentListReq req);)时,返回的字符串显示API返回了预期的JSON结果,其中data成员包含agentList数组。但将接口方法改为返回自定义的AgentList类(Task<AgentList> GetAgentList([Body] GetAgentListReq req);)后,反序列化未抛出异常,但data.agentList成员为null。直接使用System.Text.Json.JsonSerializer.Deserialize<AgentList>反序列化该字符串也得到data.agentList为null的对象,因此我怀疑是实体类定义存在问题。
接口与实体类代码
using Refit; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Digicert.Automation.API.Client { [Headers("X-DC-DEVKEY: redacted")] public interface IDigicertAutomation { [Post("/agent/basicdetails")] Task<ApiResponse<IEnumerable<AgentSummary>>> GetAgentSummary(AgentSummaryReq req); [Post("/agent/list")] //Task<string> GetAgentList([Body] GetAgentListReq req); Task<AgentList> GetAgentList([Body] GetAgentListReq req); } public class AgentSummaryReq { public required string licensekey { get; set; } public int accountId { get; set; } public int divisionId { get; set; } } public class GetAgentListReq { public int accountId { get; set; } public class Criterion { public required string key; public required string operation; public required List<string> value; } public required Criterion[] searchCriteriaList { get; set; } public required int[] divisionIds { get; set; } public int startIndex; public int pageSize; public required Dictionary<string, string> sorting { get; set; } } public class Error { public required string message { get; set; } public required List<string> detailedMessage { get; set; } public required string errorCode { get; set; } } public class AgentSummary { public required Error error { get; set; } public class Data { public required string licenseKey { get; set; } public required string agentName { get; set; } public int updatePreference { get; set; } public required string stateString { get; set; } public required string agentVersion { get; set; } public bool updateAvailable { get; set; } public bool publishUpgradeOption { get; set; } public required string emailAddresses { get; set; } } public required Data data { get; set; } } public class AgentList { public required string error { get; set; } public class AgentListdata { public required List<AgentInfo> agentList; } public required AgentListdata data {get;set;} } public class AgentInfo { public int agentId { get; set; } public required string accountId { get; set; } public required string divisionId { get; set; } public required string hostname { get; set; } public required string agentName { get; set; } public required string status { get; set; } public required string sensorName { get; set; } public required string type { get; set; } public required string agentLicense { get; set; } public int updatePreference { get; set; } public bool updateAvailable { get; set; } } }
控制台调用代码
using Microsoft.Extensions.Hosting; using Refit; using Digicert.Automation.API; using Microsoft.Extensions.DependencyInjection; using Digicert.Automation.API.Client; using static Digicert.Automation.API.Client.GetAgentListReq; using System.Diagnostics; namespace ConsoleApp1 { internal class Program { static async Task Main(string[] args) { using IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices((_, services) => { services .AddRefitClient<IDigicertAutomation>() .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://caas.digicert.com/automationws/v1/")); }).Build(); var automationClient = host.Services.GetRequiredService<IDigicertAutomation>(); var sorting = new Dictionary<string, string> { { "AGENTNAME", "ASC" }, }; var req = new GetAgentListReq() { accountId = 1349264, searchCriteriaList = Array.Empty<Criterion>(), divisionIds = Array.Empty<int>(), startIndex = 0, pageSize = 50, sorting = sorting }; var results = await automationClient.GetAgentList(req); //var result = results.Content; //var x = results.RequestMessage?.Content; //if (result?.data != null && result?.data.agentList != null) //{ // foreach (var a in result.data.agentList) // { // Console.Out.WriteLine(a.agentName); // } //} } } }
解决方案
问题出在AgentListdata类里的agentList字段——你用的是字段而不是属性。System.Text.Json默认只序列化/反序列化带get; set;的属性,字段默认会被忽略,所以反序列化时agentList始终为null。
修改AgentListdata类,把agentList改成属性:
public class AgentList { public required string error { get; set; } public class AgentListdata { // 把字段改成属性 public required List<AgentInfo> agentList { get; set; } } public required AgentListdata data { get; set; } }
另外检查GetAgentListReq里的startIndex和pageSize,同样是字段,若API要求这些参数必须序列化,也需要改成属性:
public class GetAgentListReq { public int accountId { get; set; } public class Criterion { public required string key { get; set; } public required string operation { get; set; } public required List<string> value { get; set; } } public required Criterion[] searchCriteriaList { get; set; } public required int[] divisionIds { get; set; } // 改成属性 public int startIndex { get; set; } public int pageSize { get; set; } public required Dictionary<string, string> sorting { get; set; } }
修改完成后,反序列化就能正确识别agentList数组了。
内容的提问来源于stack exchange,提问作者Ross Presser

