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
相关产品推荐
相关产品推荐

