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

如何反序列化含可变属性名的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:04:52