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

如何用C#的System.Text.Json反序列化子数组数量可变的JSON数组

问题描述

我需要将图表JSON数据反序列化为List<List<double>>,但该JSON的chart字段存在两种格式:

  1. 单个点时为单数组:
{"data" : { "chart": [ 1, 1 ] } }
  1. 多个点时为数组的数组:
{"data": {"chart": [ [ 1, 1 ],  [ 2, 2 ], [ 3, 3 ], [ 4, 4 ]]}}

目前我可通过以下类反序列到List<object>:

public class Data
{
    public List<object> chart { get; set; }
}

public class Root
{
    public Data data { get; set; }
}

但希望统一得到List<List<double>>。请问:

  1. 能否通过System.Text.Json的自定义转换器实现?具体怎么做?
  2. 能否对chart1、chart2等多个图表字段实现该逻辑?
    注:无法修改JSON生成方的代码。
解决方案

1. 用System.Text.Json自定义转换器实现

可以实现,具体步骤如下:

步骤1:编写自定义JsonConverter

创建继承自JsonConverter<List<List<double>>>的转换器,在Read方法中处理两种格式:

using System.Text.Json;
using System.Text.Json.Serialization;

public class ChartDataConverter : JsonConverter<List<List<double>>>
{
    public override List<List<double>> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType == JsonTokenType.StartArray)
        {
            // 先尝试反序列化为嵌套数组
            try
            {
                return JsonSerializer.Deserialize<List<List<double>>>(ref reader, options);
            }
            catch
            {
                // 失败则重置读取器,按单层数组处理
                reader = new Utf8JsonReader(reader.CurrentSpan);
                var singlePoint = JsonSerializer.Deserialize<List<double>>(ref reader, options);
                return new List<List<double>> { singlePoint };
            }
        }
        throw new JsonException("Invalid chart data format");
    }

    public override void Write(Utf8JsonWriter writer, List<List<double>> value, JsonSerializerOptions options)
    {
        // 序列化时统一输出嵌套数组格式
        JsonSerializer.Serialize(writer, value, options);
    }
}

步骤2:在模型中应用转换器

修改Data类,将chart字段类型改为List<List<double>>并添加转换器特性:

public class Data
{
    [JsonConverter(typeof(ChartDataConverter))]
    public List<List<double>> chart { get; set; }
}

public class Root
{
    public Data data { get; set; }
}

步骤3:反序列测试

使用常规反序列化代码即可完成转换:

var json1 = @"{""data"" : { ""chart"": [ 1, 1 ] } }";
var result1 = JsonSerializer.Deserialize<Root>(json1);
// result1.data.chart 为包含一个元素 [1,1] 的 List<List<double>>

var json2 = @"{""data"": {""chart"": [ [ 1, 1 ],  [ 2, 2 ], [ 3, 3 ], [ 4, 4 ]]}}";
var result2 = JsonSerializer.Deserialize<Root>(json2);
// result2.data.chart 为包含四个元素的 List<List<double>>

2. 对多个图表字段复用逻辑

完全可以,有两种实现方式:

方式1:给每个字段单独添加特性

直接在Data类的多个图表字段上应用同一个转换器特性:

public class Data
{
    [JsonConverter(typeof(ChartDataConverter))]
    public List<List<double>> chart { get; set; }

    [JsonConverter(typeof(ChartDataConverter))]
    public List<List<double>> chart1 { get; set; }

    [JsonConverter(typeof(ChartDataConverter))]
    public List<List<double>> chart2 { get; set; }
}

方式2:全局注册转换器

如果所有List<List<double>>类型的字段都需要该逻辑,可将转换器注册到JsonSerializerOptions中,无需逐个添加特性:

var options = new JsonSerializerOptions();
options.Converters.Add(new ChartDataConverter());

// 反序列化时传入该配置
var result = JsonSerializer.Deserialize<Root>(json, options);

这种方式下,所有模型中类型为List<List<double>>的字段都会自动应用该转换器,适合大量同类型字段的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 06:01:09