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

ASP.NET Core中如何反序列化World Bank无属性名的复杂JSON响应

世界银行异构JSON数组响应反序列化解决方案

该API返回的外层是异构JSON数组,两个元素类型完全不同,无法直接映射为单一类型的集合,可通过以下步骤处理:

1 先修正现有实体类的问题

原有实体存在两处不匹配问题,需调整:

  • WorldBankApiResponse.Value 定义为int会丢失小数精度,改为decimal?可适配空值/小数场景
  • 补充WorldBankApiResponseGlobal的Lastupdated属性
  • 新增JSON属性映射特性,适配接口返回的蛇形/小驼峰命名

修正后代码:

using System.Text.Json.Serialization;

public class WorldBankApiResponseGlobal
{
    [JsonPropertyName("page")]
    public int Page { get; set; }
    [JsonPropertyName("pages")]
    public int Pages { get; set; }
    [JsonPropertyName("per_page")]
    public int Per_Page { get; set; }
    [JsonPropertyName("total")]
    public int Total { get; set; }
    [JsonPropertyName("sourceid")]
    public string Sourceid { get; set; }
    [JsonPropertyName("sourcename")]
    public string Sourcename { get; set; }
    [JsonPropertyName("lastupdated")]
    public string Lastupdated { get; set; }
}

public class WorldBankApiIdValue
{
    [JsonPropertyName("id")]
    public string Id { get; set; }
    [JsonPropertyName("value")]
    public string Value { get; set; }
}

public class WorldBankApiResponse
{
    [JsonPropertyName("indicator")]
    public WorldBankApiIdValue Indicator { get; set; }
    [JsonPropertyName("country")]
    public WorldBankApiIdValue Country { get; set; }
    [JsonPropertyName("value")]
    public decimal? Value { get; set; }
    [JsonPropertyName("date")]
    public string Date { get; set; }
    [JsonPropertyName("countryiso3code")]
    public string Countryiso3code { get; set; }
}

2 最简方案:拆分JSON数组分别反序列化

使用.NET默认的System.Text.Json解析外层数组,按索引分别映射到对应类型,代码示例:

// 注入IHttpClientFactory后创建客户端
var client = _httpClientFactory.CreateClient();
const string requestUrl = "https://api.worldbank.org/v2/country/can/indicator/NY.GDP.PCAP.KD.ZG?format=json&mrv=2";

var response = await client.GetAsync(requestUrl);
response.EnsureSuccessStatusCode();

// 解析外层为JSON数组
var jsonContent = await response.Content.ReadAsStringAsync();
var jsonArray = System.Text.Json.Nodes.JsonNode.Parse(jsonContent)?.AsArray();

// 校验响应格式合法性
if (jsonArray == null || jsonArray.Count < 2)
{
    throw new InvalidOperationException("接口返回格式不符合预期");
}

// 分别反序列化分页元数据和指标数据
var pageMetadata = jsonArray[0].Deserialize<WorldBankApiResponseGlobal>();
var indicatorList = jsonArray[1].Deserialize<List<WorldBankApiResponse>>();

3 进阶方案:自定义转换器实现直接映射

如果需要复用该逻辑,可自定义JsonConverter,直接将响应反序列化为统一包装类,无需每次手动拆分:

3.1 定义统一返回包装类

public class WorldBankFullResponse
{
    public WorldBankApiResponseGlobal PageMetadata { get; set; }
    public List<WorldBankApiResponse> IndicatorData { get; set; }
}

3.2 实现自定义转换器

public class WorldBankResponseConverter : JsonConverter<WorldBankFullResponse>
{
    public override WorldBankFullResponse? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartArray)
        {
            throw new JsonException();
        }

        var result = new WorldBankFullResponse();
        
        // 读取第一个元素:分页元数据
        reader.Read();
        result.PageMetadata = JsonSerializer.Deserialize<WorldBankApiResponseGlobal>(ref reader, options);
        
        // 读取第二个元素:指标数组
        reader.Read();
        result.IndicatorData = JsonSerializer.Deserialize<List<WorldBankApiResponse>>(ref reader, options);
        
        // 读取数组结束标记
        reader.Read();
        return result;
    }

    public override void Write(Utf8JsonWriter writer, WorldBankFullResponse value, JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }
}

3.3 直接使用GetFromJsonAsync反序列化

var serializerOptions = new JsonSerializerOptions();
serializerOptions.Converters.Add(new WorldBankResponseConverter());

var fullResult = await client.GetFromJsonAsync<WorldBankFullResponse>(requestUrl, serializerOptions);

如果使用Newtonsoft.Json

逻辑完全一致,仅解析类改为JArray即可:

var jArray = Newtonsoft.Json.Linq.JArray.Parse(jsonContent);
var pageMetadata = jArray[0].ToObject<WorldBankApiResponseGlobal>();
var indicatorList = jArray[1].ToObject<List<WorldBankApiResponse>>();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 01:54:08