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

C#解析API返回的特殊JSON响应内容

看起来你遇到的是JSON数组到C#强类型对象的映射问题——这个API返回的产品数据是扁平数组形式,而你定义的是带命名属性的类,默认的JSON序列化工具(不管是Newtonsoft.Json还是System.Text.Json)都没法直接自动映射,不过有两种可靠的解决办法,我帮你梳理一下:

首先先明确你的输入和目标:

API返回的JSON结构(简化版)

{
  "response": {
    "results": [
      [ 1002, "Brent's Test Product o Fun", "TEST001", "1234567-", "100000000281", "12345678", "", "", true, "Brightpearl", "2020-06-18T13:38:01.000-05:00", "2021-04-27T07:45:24.000-05:00", 439, null, 74, 1, "LIVE", null ],
      [ 1003, "Brent's Test Product 2", "TEST002", "", "", "", "", "", true, "Brightpearl", "2020-08-31T00:53:26.000-05:00", "2021-04-27T07:45:24.000-05:00", 439, null, 74, 1, "LIVE", null ]
    ]
  }
}

你定义的目标类(需要先调整可空属性)

因为JSON里有null值(比如productGroupId和primarySupplierId字段),所以要把对应的属性改成可空类型,避免转换时抛出异常:

public class SkuSearchResults {
  public int productId { get; set; }
  public string productName { get; set; }
  public string SKU { get; set; }
  public string barcode { get; set; }
  public string EAN { get; set; }
  public string UPC { get; set; }
  public string ISBN { get; set; }
  public string MPN { get; set; }
  public bool stockTracked { get; set; }
  public string salesChannelName { get; set; }
  public string createdOn { get; set; }
  public string updatedOn { get; set; }
  public int brightpearlCategoryCode { get; set; }
  public int? productGroupId { get; set; } // 改为可空int
  public int brandId { get; set; }
  public int productTypeId { get; set; }
  public string productStatus { get; set; }
  public int? primarySupplierId { get; set; } // 改为可空int
}

解决方案1:手动遍历映射(简单直接)

这种方法适合快速实现,不需要额外配置序列化规则,直接解析JSON数组后逐个赋值:

使用Newtonsoft.Json的示例代码

using Newtonsoft.Json.Linq;
using System.Collections.Generic;

// 假设jsonString是API返回的完整JSON字符串
var jsonObj = JObject.Parse(jsonString);
var resultsArray = jsonObj["response"]["results"].ToObject<JArray>();

var skuList = new List<SkuSearchResults>();

foreach (var item in resultsArray)
{
    var productData = item.ToObject<JArray>();
    var sku = new SkuSearchResults
    {
        // 严格按照JSON数组的索引对应类属性
        productId = (int)productData[0],
        productName = (string)productData[1],
        SKU = (string)productData[2],
        barcode = (string)productData[3],
        EAN = (string)productData[4],
        UPC = (string)productData[5],
        ISBN = (string)productData[6],
        MPN = (string)productData[7],
        stockTracked = (bool)productData[8],
        salesChannelName = (string)productData[9],
        createdOn = (string)productData[10],
        updatedOn = (string)productData[11],
        brightpearlCategoryCode = (int)productData[12],
        // 处理null值
        productGroupId = productData[13].Type == JTokenType.Null ? null : (int?)productData[13],
        brandId = (int)productData[14],
        productTypeId = (int)productData[15],
        productStatus = (string)productData[16],
        primarySupplierId = productData[17].Type == JTokenType.Null ? null : (int?)productData[17]
    };
    skuList.Add(sku);
}

解决方案2:自定义JSON转换器(优雅复用)

如果需要多次处理这类API响应,或者希望代码更优雅,可以自定义一个JSON转换器,让序列化工具自动完成映射:

使用System.Text.Json的自定义转换器示例

using System.Text.Json;
using System.Text.Json.Serialization;
using System.Collections.Generic;

// 自定义转换器
public class SkuSearchResultsConverter : JsonConverter<SkuSearchResults>
{
    public override SkuSearchResults Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartArray)
        {
            throw new JsonException("Expected JSON array for product data");
        }

        var sku = new SkuSearchResults();
        int index = 0;

        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndArray) break;

            switch (index)
            {
                case 0: sku.productId = reader.GetInt32(); break;
                case 1: sku.productName = reader.GetString(); break;
                case 2: sku.SKU = reader.GetString(); break;
                case 3: sku.barcode = reader.GetString(); break;
                case 4: sku.EAN = reader.GetString(); break;
                case 5: sku.UPC = reader.GetString(); break;
                case 6: sku.ISBN = reader.GetString(); break;
                case 7: sku.MPN = reader.GetString(); break;
                case 8: sku.stockTracked = reader.GetBoolean(); break;
                case 9: sku.salesChannelName = reader.GetString(); break;
                case 10: sku.createdOn = reader.GetString(); break;
                case 11: sku.updatedOn = reader.GetString(); break;
                case 12: sku.brightpearlCategoryCode = reader.GetInt32(); break;
                case 13: sku.productGroupId = reader.TokenType == JsonTokenType.Null ? null : reader.GetInt32(); break;
                case 14: sku.brandId = reader.GetInt32(); break;
                case 15: sku.productTypeId = reader.GetInt32(); break;
                case 16: sku.productStatus = reader.GetString(); break;
                case 17: sku.primarySupplierId = reader.TokenType == JsonTokenType.Null ? null : reader.GetInt32(); break;
                default: 
                    // 跳过响应末尾的额外元数据
                    reader.Skip(); 
                    break;
            }
            index++;
        }
        return sku;
    }

    public override void Write(Utf8JsonWriter writer, SkuSearchResults value, JsonSerializerOptions options)
    {
        // 如果不需要把对象序列回数组,可以留空或抛出异常
        throw new NotImplementedException("Serialization from SkuSearchResults to array is not implemented");
    }
}

// 定义外层响应类
public class ApiResponse
{
    public List<SkuSearchResults> results { get; set; }
    // 如果有其他元数据字段,在这里添加对应属性
}

// 使用转换器进行反序列化
var serializerOptions = new JsonSerializerOptions();
serializerOptions.Converters.Add(new SkuSearchResultsConverter());

var apiResponse = JsonSerializer.Deserialize<ApiResponse>(jsonString, serializerOptions);
var skuList = apiResponse.results;

关键注意事项

  1. 索引对应关系:一定要严格核对JSON数组的索引和类属性的对应顺序,一旦API返回的数组顺序变化,代码会出错,建议和API文档确认字段顺序是否固定。
  2. 类型转换:注意JSON中的数据类型和C#属性的匹配,比如日期字符串直接存为string,如果需要转成DateTime,可以在映射时用DateTime.Parse()或DateTime.TryParse()处理。
  3. 空值处理:对于JSON中的null值,必须用可空类型(int?)接收,否则会抛出转换异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 14:58:15