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

含点命名的可变数量JSON属性反序列化为C#对象列表的方法

这问题我之前也碰到过,带点分隔的动态属性确实反序列化起来有点麻烦,不过用Newtonsoft.Json或者System.Text.Json都有靠谱的解决方案,我给你整理几种可行的方案:

方案一:Newtonsoft.Json 自定义转换器(最灵活)

这种方式适合需要复用逻辑的场景,通过自定义JsonConverter来解析特殊格式的属性,把它们转换成你需要的键值对列表。

首先定义目标实体类:

public class KeyValuePairItem
{
    public string Key { get; set; }
    public string Value { get; set; }
}

然后实现自定义转换器:

public class KeyValueListConverter : JsonConverter<List<KeyValuePairItem>>
{
    public override List<KeyValuePairItem> ReadJson(JsonReader reader, Type objectType, List<KeyValuePairItem> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
        var result = new List<KeyValuePairItem>();

        // 先获取count值,判断有多少组键值对
        if (!int.TryParse(jObject["SET.Key.count"]?.ToString(), out int count))
            return result;

        // 按索引配对Key和Value
        for (int i = 0; i < count; i++)
        {
            var key = jObject[$"SET.Key.{i}"]?.ToString();
            var value = jObject[$"SET.Value.{i}"]?.ToString();
            
            // 确保Key存在再添加(避免空键的情况)
            if (!string.IsNullOrEmpty(key))
            {
                result.Add(new KeyValuePairItem { Key = key, Value = value });
            }
        }

        return result;
    }

    public override void WriteJson(JsonWriter writer, List<KeyValuePairItem> value, JsonSerializer serializer)
    {
        // 如果需要把列表序列回原格式,可以在这里实现,暂时先抛出异常
        throw new NotImplementedException("序列化逻辑未实现");
    }
}

使用示例:

// 你的JSON字符串
var json = @"{""data"": {""SET.Key.0"":""Key 1"",""SET.Key.1"":""Key 2"",""SET.Key.count"":""2"",""SET.Value.0"":""10"",""SET.Value.1"":""20"",""SET.Value.count"":""2""}}";

// 解析JSON并提取data节点
var jObject = JObject.Parse(json);
var dataToken = jObject["data"];

// 使用自定义转换器反序列化
var keyValueList = dataToken.ToObject<List<KeyValuePairItem>>(new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new KeyValueListConverter() }
});

// 输出结果
foreach (var item in keyValueList)
{
    Console.WriteLine($"Key: {item.Key}, Value: {item.Value}");
}

方案二:直接遍历JObject属性(快速实现)

如果只是临时处理,不想写自定义转换器,可以直接遍历JObject的属性,筛选出需要的Key和Value并配对:

var json = @"{""data"": {""SET.Key.0"":""Key 1"",""SET.Key.1"":""Key 2"",""SET.Key.count"":""2"",""SET.Value.0"":""10"",""SET.Value.1"":""20"",""SET.Value.count"":""2""}}";

var dataObject = JObject.Parse(json)["data"] as JObject;
var keyValueList = new List<KeyValuePairItem>();

if (dataObject == null)
    return;

// 筛选所有SET.Key开头且不是count的属性
var keyProperties = dataObject.Properties()
    .Where(p => p.Name.StartsWith("SET.Key.") && !p.Name.EndsWith(".count"))
    .ToList();

foreach (var keyProp in keyProperties)
{
    // 提取索引(比如从SET.Key.0中拿到0)
    var index = keyProp.Name.Split('.').Last();
    // 找到对应的SET.Value属性
    var valueProp = dataObject.Properties().FirstOrDefault(p => p.Name == $"SET.Value.{index}");
    
    if (valueProp != null)
    {
        keyValueList.Add(new KeyValuePairItem
        {
            Key = keyProp.Value.ToString(),
            Value = valueProp.Value.ToString()
        });
    }
}

这种方式代码更简洁,适合一次性处理的场景。

方案三:System.Text.Json 自定义转换器(换库备选)

如果你想换成微软官方的System.Text.Json,思路和Newtonsoft类似,也是自定义转换器:

public class KeyValueListSystemTextJsonConverter : JsonConverter<List<KeyValuePairItem>>
{
    public override List<KeyValuePairItem> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;
        var result = new List<KeyValuePairItem>();

        // 获取count值
        if (!root.TryGetProperty("SET.Key.count", out var countElement) || 
            !int.TryParse(countElement.GetString(), out int count))
            return result;

        // 配对键值对
        for (int i = 0; i < count; i++)
        {
            if (root.TryGetProperty($"SET.Key.{i}", out var keyElement) &&
                root.TryGetProperty($"SET.Value.{i}", out var valueElement))
            {
                result.Add(new KeyValuePairItem
                {
                    Key = keyElement.GetString(),
                    Value = valueElement.GetString()
                });
            }
        }

        return result;
    }

    public override void Write(Utf8JsonWriter writer, List<KeyValuePairItem> value, JsonSerializerOptions options)
    {
        throw new NotImplementedException("序列化逻辑未实现");
    }
}

使用示例:

var json = @"{""SET.Key.0"":""Key 1"",""SET.Key.1"":""Key 2"",""SET.Key.count"":""2"",""SET.Value.0"":""10"",""SET.Value.1"":""20"",""SET.Value.count"":""2""}";

var options = new JsonSerializerOptions
{
    Converters = { new KeyValueListSystemTextJsonConverter() }
};

var keyValueList = JsonSerializer.Deserialize<List<KeyValuePairItem>>(json, options);

额外注意事项

  • 处理count不一致的情况:如果JSON中SET.Key.count和SET.Value.count的值不一样,你可以在代码中添加判断逻辑(比如抛出异常或者取较小的那个值),避免出现索引越界的问题。
  • 类型转换:如果Value是数字类型(比如int、decimal),可以修改KeyValuePairItem的Value属性类型,然后在解析的时候做类型转换(比如int.Parse(valueProp.Value.ToString()))。
  • 前缀可配置:如果前缀不是固定的SET,可以把前缀做成转换器的参数,让逻辑更通用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:51:15