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

如何在JSON反扁平化过程中正确保留数组结构?

扁平化JSON反扁平化时保留数组的处理方案

问题场景

你有如下扁平化JSON,其中Flower对应数组,通过下标0标识数组元素:

{
    "Trees.ID1.Bud.Growth Season": "",
    "Trees.ID1.Bud.Axil": "",
    "Trees.ID1.Bud.Flower.0.Sex": "",
    "Trees.ID1.Bud.Flower.0.Petal Count ": "", 
    "Trees.ID1.Bud.Flower.0.Petal Colour": ""
}

使用现有反扁平化代码后,Flower被处理成了包含0键的对象,而非数组:

{
    "Trees": {
        "ID1": {
            "Bud": {
                "Growth Season": "", 
                "Axil": "", 
                "Flower": {
                    "0": {
                        "Sex": "", 
                        "Petal Count ": "", 
                        "Petal Colour": ""
                    }
                }
            }
        }
    }
}

现有反扁平化代码如下:

from functools import reduce

def get_nested_default(d, path):
    return reduce(lambda d, k: d.setdefault(k, {}), path, d)

def set_nested(d, path, value):
    get_nested_default(d, path[:-1])[path[-1]] = value

def unflatten(d, separator='__'):
    output = {}
    for k, v in d.items():
        path = k.split(separator)
        set_nested(output, path, v)
    return output

解决方案

不需要调整扁平化格式,只需修改反扁平化的处理逻辑,增加对数组下标的识别和数组结构的创建逻辑。核心思路:

  • 遍历路径节点时,判断当前节点的下一个节点是否为纯数字(数组下标)
  • 若是,则将当前节点的类型设为数组而非对象
  • 处理数组下标时,自动扩容数组以适配下标索引,避免索引越界

修改后的反扁平化代码

from functools import reduce

def get_nested_structure(d, path):
    current = d
    for i, key in enumerate(path[:-1]):
        next_key = path[i+1]
        # 判断下一个键是否是数组下标(纯数字格式)
        if next_key.isdigit():
            idx = int(next_key)
            # 确保当前节点是数组,且长度足够容纳目标下标
            if not isinstance(current.get(key), list):
                current[key] = []
            while len(current[key]) <= idx:
                current[key].append({})
            current = current[key][idx]
        else:
            # 非数组场景,维持对象结构
            if key not in current or not isinstance(current[key], dict):
                current[key] = {}
            current = current[key]
    return current

def set_nested(d, path, value):
    parent = get_nested_structure(d, path)
    last_key = path[-1]
    # 最后一个键是数字时,按数组元素处理
    if last_key.isdigit():
        idx = int(last_key)
        if not isinstance(parent, list):
            raise ValueError("父节点必须是数组类型才能使用下标赋值")
        while len(parent) <= idx:
            parent.append({})
        parent[idx] = value
    else:
        parent[last_key] = value

def unflatten(d, separator='.'):
    output = {}
    for k, v in d.items():
        path = k.split(separator)
        set_nested(output, path, v)
    return output

测试验证

用你的扁平化JSON测试修改后的代码,会得到正确的数组结构:

{
    "Trees": {
        "ID1": {
            "Bud": {
                "Growth Season": "",
                "Axil": "",
                "Flower": [
                    {
                        "Sex": "",
                        "Petal Count ": "",
                        "Petal Colour": ""
                    }
                ]
            }
        }
    }
}

额外说明

  • 支持嵌套数组场景(比如Flower.0.Petal.0.Colour),会自动创建多层数组结构
  • 若扁平化格式中存在非连续下标(比如只有Flower.2.Sex),代码会自动填充空对象到数组的对应位置,保证下标一致性
  • 可通过修改unflatten函数的separator参数适配不同的键分隔符

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 10:17:23