You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

REST API响应中Address字段时而为对象时而为列表的反序列化问题

解决JSON反序列化时单个对象/数组兼容问题(Address字段)

问题场景

调用同一REST API获取JSON响应时,反序列化会报错,原因是响应中的Address字段格式不固定:存在多个地址时返回数组,仅一个地址时返回单个对象,导致无法直接用List<Address>类型完成反序列化。

以下是两种响应示例及原反序列化代码:

返回Address为数组的JSON

{
  "ResponseStatus": {
    "Code": "1",
    "Description": "Success"
  },
  "Address": [
    {
      "City": "CLEVELAND",
      "State": "OH",
      "PostalCode": "44126",
      "CountryCode": "US"
    },
    {
      "City": "CLEVELAND",
      "State": "WV",
      "PostalCode": "26215",
      "CountryCode": "US"
    }
  ]
}

返回Address为单个对象的JSON

{
  "ResponseStatus": {
    "Code": "1",
    "Description": "Success"
  },
  "Address": {
    "City": "CLEVELAND",
    "State": "OH",
    "PostalCode": "44126",
    "CountryCode": "US"
  }
}

原反序列化C#类代码

public class Address
{
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string CountryCode { get; set; }
}

public class ResponseStatus
{
    public string Code { get; set; }
    public string Description { get; set; }
}

public class Response
{
    public ResponseStatus ResponseStatus { get; set; }
    public List<Address> Address { get; set; }
}

// 单个对象场景下会报错的反序列化代码
Response result = JsonConvert.DeserializeObject<Response>(response);

解决方案:自定义JSON转换器

通过实现JsonConverter统一处理两种格式的转换逻辑,将单个对象或数组都转为List<Address>类型。

1. 实现自定义转换器

public class SingleOrArrayConverter<T> : JsonConverter<List<T>>
{
    public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        return token.Type switch
        {
            JTokenType.Array => token.ToObject<List<T>>(),
            JTokenType.Object => new List<T> { token.ToObject<T>() },
            _ => throw new JsonSerializationException($"Unexpected token type: {token.Type}")
        };
    }

    public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer)
    {
        // 可选:序列化时根据列表长度自动输出单个对象或数组
        if (value.Count == 1)
        {
            serializer.Serialize(writer, value[0]);
        }
        else
        {
            serializer.Serialize(writer, value);
        }
    }
}

2. 修改Response类绑定转换器

在Address属性上添加特性,指定使用自定义转换器:

public class Response
{
    public ResponseStatus ResponseStatus { get; set; }
    [JsonConverter(typeof(SingleOrArrayConverter<Address>))]
    public List<Address> Address { get; set; }
}

3. 测试反序列化

修改后两种格式的JSON都能正常完成反序列化:

// 单个对象场景
var singleResponse = "{...单个Address的JSON内容...}";
var result1 = JsonConvert.DeserializeObject<Response>(singleResponse);
// result1.Address 包含1个Address元素

// 数组场景
var arrayResponse = "{...Address数组的JSON内容...}";
var result2 = JsonConvert.DeserializeObject<Response>(arrayResponse);
// result2.Address 包含多个Address元素

替代方案:动态手动处理(不推荐)

如果不想编写自定义转换器,也可以先将JSON解析为JObject,手动判断Address的类型后再转换:

var jObject = JObject.Parse(response);
var responseObj = new Response
{
    ResponseStatus = jObject["ResponseStatus"].ToObject<ResponseStatus>()
};

var addressToken = jObject["Address"];
responseObj.Address = addressToken.Type switch
{
    JTokenType.Array => addressToken.ToObject<List<Address>>(),
    JTokenType.Object => new List<Address> { addressToken.ToObject<Address>() },
    _ => new List<Address>()
};

此方式代码冗余、复用性差,仅适合临时场景。

内容的提问来源于stack exchange,提问作者Shibu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 03:42:50