C# .NET 6中如何将JSON对象反序列化为自定义数组模型
解答
没有仅靠内置序列化特性、完全不写自定义代码就能实现该需求的方案:接口返回的Columns是键为动态数字的对象结构,和目标数组属于完全不同的JSON结构类型,内置的属性映射、类型转换特性只能处理静态结构的匹配,无法自动展开动态键为数组元素。
但你只需要写极少量的轻量转换逻辑,复用JSON库自带的序列化能力,不需要手动逐节点解析JSON,两种常用库的实现方式如下:
首先定义你需要的目标模型:
// 根响应模型 public class ApiResponse { // 后续给这个属性挂载转换器即可 public List<Column> Columns { get; set; } } // 你期望的列结构 public class Column { public string Number { get; set; } public List<string> Fuels { get; set; } }
方案1:使用Newtonsoft.Json
实现一个针对List<Column>的自定义转换器,核心逻辑是先把动态键对象反序列化为字典,再做一次结构映射:
using Newtonsoft.Json; public class ColumnListConverter : JsonConverter<List<Column>> { // 内部临时类,匹配接口返回的单条列结构 private class ColumnRaw { public List<string> Fuels { get; set; } } public override List<Column> ReadJson(JsonReader reader, Type objectType, List<Column> existingValue, bool hasExistingValue, JsonSerializer serializer) { // 复用内置能力直接把动态对象转成字典 var rawDict = serializer.Deserialize<Dictionary<string, ColumnRaw>>(reader); // 映射为目标结构 return rawDict?.Select(kv => new Column { Number = kv.Key, Fuels = kv.Value.Fuels }).ToList(); } public override void WriteJson(JsonWriter writer, List<Column> value, JsonSerializer serializer) { // 不需要序列化回原结构可以直接留空抛异常,需要的话反向转字典序列化即可 throw new NotImplementedException(); } }
给属性加特性即可生效:
public class ApiResponse { [JsonConverter(typeof(ColumnListConverter))] public List<Column> Columns { get; set; } }
方案2:使用.NET 6内置System.Text.Json
逻辑和Newtonsoft版本一致,仅转换器基类和API有区别:
using System.Text.Json; using System.Text.Json.Serialization; public class ColumnListConverter : JsonConverter<List<Column>> { private class ColumnRaw { public List<string> Fuels { get; set; } } public override List<Column> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var rawDict = JsonSerializer.Deserialize<Dictionary<string, ColumnRaw>>(ref reader, options); return rawDict?.Select(kv => new Column { Number = kv.Key, Fuels = kv.Value.Fuels }).ToList(); } public override void Write(Utf8JsonWriter writer, List<Column> value, JsonSerializerOptions options) { throw new NotImplementedException(); } }
挂载特性的方式:
public class ApiResponse { [JsonConverter(typeof(ColumnListConverter))] public List<Column> Columns { get; set; } }
这种实现方式没有冗余代码,所有JSON解析逻辑都由库本身完成,你只需要做最后一步结构映射,后续如果接口给Columns新增了字段,只需要同步修改内部的
ColumnRaw类和映射逻辑即可,比自动生成一堆_1/_2的冗余类维护成本低很多。
内容的提问来源于stack exchange,提问作者hamaronooo
相关产品推荐
相关产品推荐

