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

C#中使用System.Text.Json将JSON数组反序列化为实体模型

解决方案:自定义JsonConverter实现数组到实体类的反序列化

当然可以通过自定义JsonConverter<DataModel>来搞定这个需求!因为你的JSON里data字段是一个有序数组,而目标是把它映射到有命名属性的DataModel类,System.Text.Json默认不支持这种数组到对象的直接映射,所以自定义转换器是最直接的方案。

步骤1:定义你的实体类

首先确保DataModel的属性顺序和JSON数组的元素顺序严格对应(JSON数组是按序存储的,转换器里会按顺序读取元素):

public class Example1
{
    public int ResponseCode { get; set; }
    // 如果JSON键名和属性名大小写不一致,可添加[JsonPropertyName("data")]标记
    public DataModel Data { get; set; }
}

public class DataModel
{
    public DateTime Date { get; set; }
    public string SomeString { get; set; }
    public int NumericValue { get; set; } // 对应JSON中的1230
    public decimal DecimalValue { get; set; } // 对应9.025,用decimal比double更精确
}

步骤2:实现自定义JsonConverter

创建转换器类,重写Read方法(处理反序列化)和Write方法(可选,用于把DataModel转回数组格式):

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

public class DataModelConverter : JsonConverter<DataModel>
{
    public override DataModel Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 验证当前JSON令牌是否为数组开头
        if (reader.TokenType != JsonTokenType.StartArray)
        {
            throw new JsonException("DataModel必须从JSON数组开始解析");
        }

        var dataModel = new DataModel();
        int elementIndex = 0;

        // 遍历数组中的每个元素
        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndArray)
            {
                break;
            }

            switch (elementIndex)
            {
                case 0:
                    // 解析带时区的DateTime,GetDateTime()会自动处理UTC格式
                    dataModel.Date = reader.GetDateTime();
                    break;
                case 1:
                    dataModel.SomeString = reader.GetString();
                    break;
                case 2:
                    dataModel.NumericValue = reader.GetInt32();
                    break;
                case 3:
                    dataModel.DecimalValue = reader.GetDecimal();
                    break;
                default:
                    // 忽略多余的数组元素,也可根据业务需求抛出异常
                    reader.Skip();
                    break;
            }

            elementIndex++;
        }

        return dataModel;
    }

    public override void Write(Utf8JsonWriter writer, DataModel value, JsonSerializerOptions options)
    {
        // 如果需要把DataModel序列化为数组格式,实现此方法
        writer.WriteStartArray();
        writer.WriteStringValue(value.Date);
        writer.WriteStringValue(value.SomeString);
        writer.WriteNumberValue(value.NumericValue);
        writer.WriteNumberValue(value.DecimalValue);
        writer.WriteEndArray();
    }
}

步骤3:使用转换器进行反序列化

有两种方式应用这个转换器:

方式一:在DataModel类上标记特性

直接在DataModel类上添加特性,序列化/反序列化时会自动使用该转换器:

[JsonConverter(typeof(DataModelConverter))]
public class DataModel
{
    // ... 属性定义 ...
}

// 反序列化代码
string json = @"{""ResponseCode"":200,""data"":[""2016-08-05T15:49:15.157000+00:00"",""SomeString"",1230,9.025]}";
Example1 result = JsonSerializer.Deserialize<Example1>(json);

方式二:在JsonSerializerOptions中添加转换器

如果不想修改DataModel类,可以在反序列化时手动传入配置:

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

string json = @"{""ResponseCode"":200,""data"":[""2016-08-05T15:49:15.157000+00:00"",""SomeString"",1230,9.025]}";
Example1 result = JsonSerializer.Deserialize<Example1>(json, options);

注意事项

  • 顺序严格性:JSON数组的元素顺序必须和DataModel属性的映射顺序完全一致,否则会出现赋值错误。
  • 类型兼容性:确保JSON元素的类型和目标属性类型匹配,比如如果JSON里的数字是字符串类型,需要手动转换(用reader.GetString()后再转成int/decimal)。
  • 时区处理:你的JSON DateTime带+00:00时区,reader.GetDateTime()会自动解析为UTC时间,如果需要转成本地时间,可以在赋值时调用ToLocalTime()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 14:32:51