【问题标题】:How do I reconstruct JSON from a dot delimeted list of strings?如何从点分隔的字符串列表构造 JSON?
【发布时间】:2016-06-29 08:37:11
【问题描述】:

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

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 负载的 path,那么我有大约 200 个未排序的路径(无论顺序如何,转换都应该起作用),所有这些路径的深度最多为 8 个点热切地希望成为他们原始结构的一部分。我尝试过使用递归来解决这个问题,pandas 从内部节点中排​​序叶节点(荒谬?),疯狂的列表字典列表列表谁知道,甚至 autovivification

毁灭和绝望的领域

这是我编写/放弃的 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)

【问题讨论】:

    标签: python json dictionary nested nested-loops


    【解决方案1】:

    给你:

    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
        }
    }
    

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

    【讨论】:

    • 您至少应该在点 (.) 上拆分各个路径,而不是在其字符上进行迭代...
    • 哎呀忘记添加了!这是一个预处理步骤。抱歉,这里已经是凌晨了。
    • @SergeBallesta 我最初是这样做的。我编辑了答案以反映该步骤。我还将实现更改为使用 enumerate,因为它更 Python 并且提高了可读性。
    • @juanpa.arrivillaga - 你会和我建立一夫一妻制的编码关系吗?谢谢!不过,说真的,一旦我将None 分配更改为{},这就像一个魅力。
    【解决方案2】:

    试用dpath 模块,它可用于轻松添加/过滤/搜索字典。通过将点替换为“/”字符,您可以创建所需的 dict

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      • 2020-12-26
      • 1970-01-01
      相关资源
      最近更新 更多