如何从点分隔的字符串列表中重建 JSON?

How do I reconstruct JSON from a dot delimeted list of strings?

有人会认为这样做很容易。我发誓是,只是...我似乎无法弄明白。如何转换:

terrible_way_to_describe_nested_json=['a.b.c','a.b.d','a.e','a.f','g.h']

进入

{
    "a": {
        "b": {
            "c": None,
            "d": None
        },
        "e": None,
        "f": None
    },
    "g": {
        "h": None
    }
}

如果您考虑 'a.b.c' 解构 JSON 负载的 路径 ,那么我有大约 200 个这些未排序的路径(无论如何转换都应该有效顺序)高达 8 个点深,都热切希望成为其原始结构的一部分。我已经尝试使用递归来解决这个问题,pandas 从内部节点中对叶节点进行排序(荒谬吗?),疯狂的列表字典列表谁知道,甚至 autovivification.

废墟与绝望之地

这是我 written/abandoned 的 6 个部分实现之一。它甚至在边缘节点之前剥离嵌套键层,然后我就失去理智了。我几乎建议忽略它。

def dot_to_json(dotted_paths):
    scope_map=[line.split('.') for line in dotted_paths] #Convert dots list to strings
    # Sort and group list of strings according to length of list. longest group is last
    b=[]
    for index in range(max([len(x) for x in scope_map])+1):
        a=[]
        for item in scope_map:
            if len(item)==index:
                a.append(item)
        b.append(a)
    sorted_nest=[x for x in b if x] # finally group according to list length
    #Point AA
    # group string list 'prefix' with key:value
    child_path=[]
    for item in sorted_nest[-1]:
        child_path.append([item[:-1],{item[-1]:None}])
    # peel back a layer
    new_child_path=[]
    for scope in scope_map[-2]:
        value=None # set value to None if fringe node
        for index, path in enumerate(child_path):
            if path[0]==scope: # else, save key + value as a value to the new prefix key
                value=path[1]
                child_path.pop(index) # 'move' this path off child_path list
        new_child_path.append([scope[:-1],{scope[-1]:value}])
    new_child_path+=child_path
    #Point BB...
    #Loop in some intelligent way between Point AA and Point BB
    return new_child_path
#%%
dotted_json=['a.b.c','a.b.d','a.e','a.f','g.h']

scope_map=dot_to_json(dotted_json)

试试dpath模块,它可以很容易地用于add/filter/search字典。通过用“/”字符替换点,您可以创建所需的 dict

给你:

In [5]: terrible_way_to_describe_nested_json=['a.b.c','a.b.d','a.e','a.f','g.h']

In [6]: terrible_way_to_describe_nested_json = [s.split('.') for s in terrible_way_to_describe_nested_json]

In [7]: data = {}

In [8]: for path in terrible_way_to_describe_nested_json:
   ....:     curr = data
   ....:     for i, node in enumerate(path):
   ....:         if i == len(path) - 1:
   ....:             curr[node] = None
   ....:         else:
   ....:             curr = curr.setdefault(node,{})
   ....:             

In [9]: data
Out[9]: {'a': {'b': {'c': None, 'd': None}, 'e': None, 'f': None}, 'g': {'h': None}}

现在使用 json 模块进行漂亮的打印可以得到:

{
    "a": {
        "f": null,
        "b": {
            "d": null,
            "c": null
        },
        "e": null
    },
    "g": {
        "h": null
    }
}

这两个应该是等价的,但顺序不对,或者至少打印顺序不对。