如何在C#中处理API返回的两种异构响应(Newtonsoft.Json)
处理API响应中message字段多类型的问题
针对API返回的message字段在成功时为对象、失败时为字符串的情况,有以下几种可行的处理方案:
方案一:先解析为JObject再按需处理
先将响应字符串反序列化为JObject,通过status字段判断结果类型后,再分别处理message字段:
var responseJObject = JObject.Parse(iziDataKtpOcrResponse); string status = responseJObject["status"].ToString(); if (status == "OK") { var successResponse = new IziDataKtpOcrResponseMessage { Status = status, message = responseJObject["message"].ToObject<IziDataKtpOcrResponseMessageData>() }; // 执行成功业务逻辑 } else if (status == "FAIL") { string errorMessage = responseJObject["message"].ToString(); // 处理失败场景,比如记录错误、提示用户等 }
方案二:自定义Json转换器适配多类型字段
通过编写自定义转换器,让模型的message字段同时支持对象和字符串两种类型:
步骤1:编写自定义转换器
public class MessageConverter : JsonConverter<IziDataKtpOcrResponseMessageData> { public override IziDataKtpOcrResponseMessageData ReadJson(JsonReader reader, Type objectType, IziDataKtpOcrResponseMessageData existingValue, bool hasExistingValue, JsonSerializer serializer) { // 处理字符串类型的message(失败场景) if (reader.TokenType == JsonToken.String) { return new IziDataKtpOcrResponseMessageData { ErrorMessage = reader.Value.ToString() }; } // 处理对象类型的message(成功场景) else if (reader.TokenType == JsonToken.StartObject) { return serializer.Deserialize<IziDataKtpOcrResponseMessageData>(reader); } throw new JsonException("message字段类型不符合预期"); } public override void WriteJson(JsonWriter writer, IziDataKtpOcrResponseMessageData value, JsonSerializer serializer) { // 序列化时根据是否有错误信息选择输出格式(可选,根据需求实现) if (!string.IsNullOrEmpty(value.ErrorMessage)) { writer.WriteValue(value.ErrorMessage); } else { serializer.Serialize(writer, value); } } }
步骤2:修改数据模型
在原有模型基础上新增错误信息字段,并给message属性标记转换器:
public class IziDataKtpOcrResponseMessageData { // 原有业务字段 public string name { get; set; } public string id { get; set; } public string pob { get; set; } public string dob { get; set; } public string gender { get; set; } public string address { get; set; } public string rt { get; set; } public string rw { get; set; } public string village { get; set; } public string district { get; set; } public string religion { get; set; } public string marital_status { get; set; } public string work { get; set; } public string nationnality { get; set; } public string city { get; set; } public string province { get; set; } // 新增错误信息字段 public string ErrorMessage { get; set; } } public class IziDataKtpOcrResponseMessage { public string Status { get; set; } [JsonConverter(typeof(MessageConverter))] public IziDataKtpOcrResponseMessageData message { get; set; } }
步骤3:正常反序列化并处理
var response = JsonConvert.DeserializeObject<IziDataKtpOcrResponseMessage>(iziDataKtpOcrResponse); if (response.Status == "OK") { // 使用response.message中的业务数据 } else if (response.Status == "FAIL") { string errorMsg = response.message.ErrorMessage; // 处理错误逻辑 }
方案三:使用动态类型(dynamic)
这种方式代码简洁,但缺乏类型检查,适合快速测试或小型项目:
dynamic response = JsonConvert.DeserializeObject(iziDataKtpOcrResponse); string status = response.status; if (status == "OK") { // 直接访问response.message.name、response.message.id等字段 } else if (status == "FAIL") { string errorMsg = response.message; // 处理错误 }
各方案优缺点对比
- 方案一:灵活度高,无需修改现有模型,适合简单场景;缺点是需要手动拆分反序列化步骤。
- 方案二:类型安全,代码结构清晰,适合长期维护的项目;缺点是需要编写额外的转换器代码。
- 方案三:代码最简洁,但运行时无类型校验,容易出现未捕获的错误,不推荐在大型项目中使用。
内容的提问来源于stack exchange,提问作者MursyidinAdnan
相关产品推荐
相关产品推荐

