如何在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
相关产品推荐
相关产品推荐

