如何反序列化含可变属性名的JSON?优先使用System.Text.Json
解决方案:处理可变属性名的JSON反序列化
核心问题分析
你的JSON中parts节点是键值对对象(而非数组),但你定义的ProductInfo类中Parts属性是List<ProductInfo>,类型不匹配导致反序列化失败。解决思路是让属性类型与JSON结构对齐,或者通过自定义转换器适配。
优先方案:System.Text.Json 实现
方法1:修改属性类型为字典(推荐)
直接将ProductInfo中的Parts类型从List<ProductInfo>改为Dictionary<string, ProductInfo>,这样可以直接匹配JSON的键值对结构,同时保留每个部件的标识名称(如876-08533、cabinet-1)。
修改后的类定义:
public class Properties { public string Measure { get; set; } } public class ProductInfo { public int Depth { get; set; } public int Width { get; set; } public Dictionary<string, ProductInfo> Parts { get; set; } // 修改为字典类型 public string Description { get; set; } public Properties Properties { get; set; } } // 根对象类 public class RootObject { public int Id { get; set; } public List<Row> Rows { get; set; } public string Quotation { get; set; } } public class Row { public int CostPriceIncludingVat { get; set; } public ProductInfo ProductInfo { get; set; } }
反序列化代码:
string json = "{你的JSON字符串}"; var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true // 忽略大小写差异 }; var root = JsonSerializer.Deserialize<RootObject>(json, options);
方法2:自定义转换器(保留List)
如果必须用List<ProductInfo>且不需要保留部件名称,可以编写自定义转换器,将JSON对象的值提取为列表:
public class PartsConverter : JsonConverter<List<ProductInfo>> { public override List<ProductInfo> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 读取JSON对象,将所有值转为ProductInfo并收集到列表 var partsDict = JsonSerializer.Deserialize<Dictionary<string, ProductInfo>>(ref reader, options); return partsDict?.Values.ToList() ?? new List<ProductInfo>(); } public override void Write(Utf8JsonWriter writer, List<ProductInfo> value, JsonSerializerOptions options) { // 序列化时如果需要转回对象格式,可自行实现 throw new NotImplementedException(); } }
然后在ProductInfo类的Parts属性上标记转换器:
public class ProductInfo { public int Depth { get; set; } public int Width { get; set; } [JsonConverter(typeof(PartsConverter))] public List<ProductInfo> Parts { get; set; } public string Description { get; set; } public Properties Properties { get; set; } }
反序列化时使用默认选项即可。
Newtonsoft.Json 实现
同样先修改Parts类型为Dictionary<string, ProductInfo>,类定义和System.Text.Json版本一致,反序列化代码:
string json = "{你的JSON字符串}"; var root = JsonConvert.DeserializeObject<RootObject>(json, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() // 适配大小写 });
如果要保留List<ProductInfo>,可以用自定义转换器:
public class NewtonsoftPartsConverter : JsonConverter<List<ProductInfo>> { public override List<ProductInfo> ReadJson(JsonReader reader, Type objectType, List<ProductInfo> existingValue, bool hasExistingValue, JsonSerializer serializer) { var partsDict = serializer.Deserialize<Dictionary<string, ProductInfo>>(reader); return partsDict?.Values.ToList() ?? new List<ProductInfo>(); } public override void WriteJson(JsonWriter writer, List<ProductInfo> value, JsonSerializer serializer) { throw new NotImplementedException(); } }
然后在属性上标记:
[JsonConverter(typeof(NewtonsoftPartsConverter))] public List<ProductInfo> Parts { get; set; }
内容的提问来源于stack exchange,提问作者TheSjoerd
相关产品推荐
相关产品推荐

