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

C#中处理API返回JSON空数组与对象的反序列化问题

解决方案

问题根源在于API返回的data和errors字段类型动态切换:正常场景下data是对象、errors是空数组;错误场景下data是空数组、errors是对象,现有模型无法兼容两种类型,导致反序列化失败。以下是两种可行的解决方式:

方案一:自定义Json转换器(类型安全,推荐)

步骤1:实现通用转换逻辑

创建两个自定义JsonConverter,分别处理「对象/空数组」和「数组/对象」的动态转换:

// 用于data字段:兼容对象或空数组,空数组时返回null
public class ObjectOrEmptyArrayConverter<T> : JsonConverter<T>
{
    public override T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartArray)
        {
            var array = JArray.Load(reader);
            return array.Count == 0 ? default(T) : throw new JsonSerializationException("非空数组无法转换为目标对象类型");
        }
        else if (reader.TokenType == JsonToken.StartObject)
        {
            return serializer.Deserialize<T>(reader);
        }
        return default(T);
    }

    public override void WriteJson(JsonWriter writer, T value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

// 用于errors字段:兼容数组或单个对象,对象时自动包装为List
public class ArrayOrObjectConverter<T> : JsonConverter<List<T>>
{
    public override List<T> ReadJson(JsonReader reader, Type objectType, List<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.StartObject)
        {
            var obj = serializer.Deserialize<T>(reader);
            return new List<T> { obj };
        }
        else if (reader.TokenType == JsonToken.StartArray)
        {
            return serializer.Deserialize<List<T>>(reader);
        }
        return new List<T>();
    }

    public override void WriteJson(JsonWriter writer, List<T> value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

步骤2:更新模型并添加转换器特性

为模型的data和errors字段绑定对应的转换器:

public class RequestPaymentVerifyResponseModel
{
    [JsonConverter(typeof(ObjectOrEmptyArrayConverter<VerifyData>))]
    public VerifyData data { get; set; }

    [JsonConverter(typeof(ArrayOrObjectConverter<Errors>))]
    public List<Errors> errors { get; set; }
}

public class VerifyData
{
    public int code { get; set; }
    public string message { get; set; }
    public string card_hash { get; set; }
    public string card_pan { get; set; }
    public int ref_id { get; set; }
    public string fee_type { get; set; }
    public int fee { get; set; }
}

public class Errors
{
    public int code { get; set; }
    public string message { get; set; }
    public List<object> validations { get; set; }
}

步骤3:使用原有反序列化代码

现在可以直接复用你的原代码,两种返回格式都会被正确处理:

var result = await client.PostAsJsonAsync("pg/v4/payment/verify.json", parameters);
var response = JsonConvert.DeserializeObject<RequestPaymentVerifyResponseModel>(await result.Content.ReadAsStringAsync());

方案二:手动解析JToken(快速实现)

如果不想编写自定义转换器,可先将JSON解析为JObject,手动判断字段类型后再转换为目标模型:

var result = await client.PostAsJsonAsync("pg/v4/payment/verify.json", parameters);
var jsonString = await result.Content.ReadAsStringAsync();
var jRoot = JObject.Parse(jsonString);

var response = new RequestPaymentVerifyResponseModel();

// 处理data字段
if (jRoot["data"].Type == JTokenType.Object)
{
    response.data = jRoot["data"].ToObject<VerifyData>();
}
else
{
    // 错误场景下data是空数组,设为null
    response.data = null;
}

// 处理errors字段
if (jRoot["errors"].Type == JTokenType.Object)
{
    // 错误场景下errors是单个对象,包装为List
    response.errors = new List<Errors> { jRoot["errors"].ToObject<Errors>() };
}
else
{
    // 正常场景下errors是空数组,直接转换为List
    response.errors = jRoot["errors"].ToObject<List<Errors>>();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:57:40