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

如何将嵌套JSON数组正确反序列化为CandlestickData对象数组?

解决JSON数组反序列化为CandlestickData数组的错误

这个问题我之前也碰到过,核心是对[JsonArray]特性的用法理解偏差导致的,咱们一步步拆解解决:

问题根源

你提供的JSON是数组嵌套数组的结构:外层是K线数据集合,每个K线是包含12个元素的数组。而你给CandlestickData类添加了[JsonArray]特性——这个特性的作用是告诉Json.NET把单个类实例序列化成JSON数组,反过来,当你反序列化时,Json.NET会误以为CandlestickData是一个集合类型,试图去创建并填充它,但它本质是普通POCO类,所以抛出了Cannot create and populate list type CandlestickData错误。

另外,你尝试把decimal改成string也没用,因为错误的根源不是类型匹配,而是类的特性标记错误。

正确解决方案

方案1:移除[JsonArray],用构造函数匹配数组顺序

这是最贴合Newtonsoft.Json设计的方式,移除类上的[JsonArray],然后添加一个参数顺序和JSON数组元素完全一致的构造函数,再加上[JsonConstructor]特性让Json.NET识别它:

public class CandlestickData
{
    public long OpenTime { get; set; }
    public decimal Open { get; set; }
    public decimal High { get; set; }
    public decimal Low { get; set; }
    public decimal Close { get; set; }
    public decimal Volume { get; set; }
    public long CloseTime { get; set; }
    public decimal QuoteAssetVolume { get; set; }
    public long NumberOfTrades { get; set; }
    public decimal TakerBuyBaseAssetVolume { get; set; }
    public decimal TakerBuyQuoteAssetVolume { get; set; }
    public decimal Ignore { get; set; }

    // 构造函数参数顺序严格对应JSON数组的12个元素
    [JsonConstructor]
    public CandlestickData(
        long openTime,
        decimal open,
        decimal high,
        decimal low,
        decimal close,
        decimal volume,
        long closeTime,
        decimal quoteAssetVolume,
        long numberOfTrades,
        decimal takerBuyBaseAssetVolume,
        decimal takerBuyQuoteAssetVolume,
        decimal ignore)
    {
        OpenTime = openTime;
        Open = open;
        High = high;
        Low = low;
        Close = close;
        Volume = volume;
        CloseTime = closeTime;
        QuoteAssetVolume = quoteAssetVolume;
        NumberOfTrades = numberOfTrades;
        TakerBuyBaseAssetVolume = takerBuyBaseAssetVolume;
        TakerBuyQuoteAssetVolume = takerBuyQuoteAssetVolume;
        Ignore = ignore;
    }
}

之后直接用你原来的反序列化代码就行,完全不需要改动:

var candlesticks = JsonConvert.DeserializeObject<CandlestickData[]>(content);

方案2:手动映射原始数组(适合不想写构造函数的场景)

如果觉得写构造函数麻烦,可以先把JSON反序列化成原始的二维数组,再手动映射到CandlestickData对象:

// 先反序列化为原始的object二维数组
var rawKlineData = JsonConvert.DeserializeObject<object[][]>(content);

// 逐个映射到CandlestickData
var candlesticks = rawKlineData.Select(kline => new CandlestickData
{
    OpenTime = Convert.ToInt64(kline[0]),
    Open = Convert.ToDecimal(kline[1]),
    High = Convert.ToDecimal(kline[2]),
    Low = Convert.ToDecimal(kline[3]),
    Close = Convert.ToDecimal(kline[4]),
    Volume = Convert.ToDecimal(kline[5]),
    CloseTime = Convert.ToInt64(kline[6]),
    QuoteAssetVolume = Convert.ToDecimal(kline[7]),
    NumberOfTrades = Convert.ToInt64(kline[8]),
    TakerBuyBaseAssetVolume = Convert.ToDecimal(kline[9]),
    TakerBuyQuoteAssetVolume = Convert.ToDecimal(kline[10]),
    Ignore = Convert.ToDecimal(kline[11])
}).ToArray();

这种方式更直观,缺点是需要手动写每个属性的转换逻辑,适合属性数量不多的场景。

验证测试

用你的JSON字符串测试方案1,会成功生成3个CandlestickData实例,每个属性都能正确赋值,比如第一个实例的OpenTime是1627948800000,Open是33361.77m,完全符合JSON里的数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 05:37:34