第三方API模糊类型响应的JSON反序列化方案问询
处理API歧义错误响应的优雅方案
这个API返回的两种error格式确实挺闹心的,你现在用object兜底的方案虽然能凑合用,但确实不够优雅,还存在二次反序列化的性能损耗和潜在的类型转换风险。我给你两个更靠谱的实现方式:
方案1:自定义JsonConverter(推荐)
直接写一个Json转换器,一次性处理两种格式的反序列化,不用后续再做额外转换,性能和可读性都更好。
首先定义转换器:
public class ErrorResponseConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(Response); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var response = new Response(); var jsonObject = JObject.Load(reader); var errorToken = jsonObject["error"]; if (errorToken == null) return response; switch (errorToken.Type) { case JTokenType.String: response.Error = errorToken.Value<string>(); break; case JTokenType.Object: response.ObjectError = errorToken.ToObject<ObjectError>(serializer); response.Error = response.ObjectError.Message; // 同步错误消息到Error属性,方便统一调用 break; } return response; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 如果需要序列化Response,这里可以根据实际需求选择输出格式 var response = (Response)value; var jsonObject = new JObject(); if (response.ObjectError != null) { jsonObject["error"] = JObject.FromObject(response.ObjectError, serializer); } else if (!string.IsNullOrEmpty(response.Error)) { jsonObject["error"] = response.Error; } jsonObject.WriteTo(writer); } }
然后给你的Response类加上转换器标记:
[JsonConverter(typeof(ErrorResponseConverter))] public class Response { public string Error { get; set; } public ObjectError ObjectError { get; set; } } public class ObjectError { [JsonProperty("message")] public string Message { get; set; } [JsonProperty("status_code")] public string StatusCode { get; set; } }
这样反序列化时,不管API返回的是字符串错误还是对象错误,都会自动映射到对应的属性,一步到位,完全不需要额外处理。
方案2:用JToken替代Object(简化优化版)
如果不想写转换器,也可以优化你现有的代码,用JToken来接收error字段,避免object带来的不确定性和二次反序列化:
public class Response { [JsonProperty("error")] private JToken _errorToken; // 获取字符串格式的错误 public string ErrorAsString => _errorToken?.Type == JTokenType.String ? _errorToken.Value<string>() : null; // 获取对象格式的错误 public ObjectError ErrorAsObject => _errorToken?.Type == JTokenType.Object ? _errorToken.ToObject<ObjectError>() : null; // 统一获取错误消息(不管是哪种格式) public string Error => ErrorAsString ?? ErrorAsObject?.Message; } public class ObjectError { [JsonProperty("message")] public string Message { get; set; } [JsonProperty("status_code")] public string StatusCode { get; set; } }
JToken是Json.NET的原生类型,能直接判断error的类型是字符串还是对象,转换也更安全,不用先把对象转成JSON字符串再反序列化,比你原来的object方案更可靠。
对比你当前的方案
你现在用object的问题主要有两点:
- 当
error是对象时,Error.ToString()会输出JSON字符串,后续反序列化可能因为格式变动出问题; - 二次反序列化会额外消耗性能,虽然单次影响不大,但高频调用时会有累积效应。
用上面两种方案都能解决这些问题,其中自定义转换器的方式扩展性更强,如果后续API又加了新的错误格式,只需要在转换器里加个分支就行。
内容的提问来源于stack exchange,提问作者CrnaStena
相关产品推荐
相关产品推荐

