【问题标题】:Convert multiple lines of string into a JSON based on a delimiter根据分隔符将多行字符串转换为 JSON
【发布时间】:2021-08-20 00:45:26
【问题描述】:

我对将多行字符串转换为 JSON 树结构的想法完全迷失了

所以,我在特定的 excel 列下有如下多行字符串:

/abc/a[2]/a/x[1]
/abc/a[2]/a/x[2]

由于上述字符串包含分隔符 / ,我可以使用它们来创建父子关系并将它们转换为 Python 字典(或)JSON,如下所示:

{
  "tag": "abc",
  "child": [
    {
      "tag": "a[2]",
      "child": [
        {
          "tag": "a",
          "child": [
            {
              "tag": "a",
              "child": [
                {
                  "tag": "x[1]"
                },
                {
                  "tag": "x[2]"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

我无法为我的项目的这一部分提出逻辑,因为我需要寻找 [1],[2] 的存在并将它们分配给一个共同的父级,这需要以某种递归方式完成适用于任何长度的字符串的方式。请帮助我解决 Python 中的任何代码逻辑或向我提供建议。非常感谢!!

其他更新: 只是想知道是否也可以在 JSON 结构中包含其他列的数据。

例如:如果excel包含以下三列2行

tag text type
/abc/a[2]/a/x[1] Hello string
/abc/a[2]/a/x[2] World string

与原始问题中的 JSON 一起,是否可以将这些其他列信息添加为 JSON 中的键值属性(到相应的最内层子嵌套),如下所示。 这些不遵循相同的“/”分隔符格式,因此我不确定是否接近这个..

{
  "tag": "abc",
  "child": [
    {
      "tag": "a[2]",
      "child": [
        {
          "tag": "a",
          "child": [
            {
              "tag": "a",
              "child": [
                {
                  "tag": "x[1]",
                  "text": "Hello",
                  "type": "string"
                },
                {
                  "tag": "x[2]",
                  "text": "World",
                  "type": "string"
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

P.S:我觉得将数据添加到最里面的孩子以避免信息冗余是合适的......请随时建议以任何其他适当的方式包括这些其他列。

【问题讨论】:

  • 我的答案中的 to_dict 函数是否适合您,或者您想要某种不同的函数?
  • 是的,您的代码运行良好。我只需将其连接到我的 excel 列,遍历每一行并从中创建 JSON。此外,还包括其他列作为键值对。我刚刚遇到了 JSON 的麻烦,这两种解决方案都像一个魅力。再次感谢,伙计
  • 列之间的分隔符是什么?像使用 1. 示例数据一样将新示例数据发布为字符串。

标签: python json recursion


【解决方案1】:

你可以使用递归collections.defaultdict:

import collections, json
def to_tree(d):
   v = collections.defaultdict(list)
   for [a, *b], *c in d:
      v[a].append([b, *c])
   return [{'tag':a, **({'child':to_tree(b)} if all(j for j, *_ in b) else dict(zip(['text', 'type'], b[0][-2:])))} 
            for a, b in v.items()]

col_data = [['/abc/a[2]/a/x[1]', 'Hello', 'string'], ['/abc/a[2]/a/x[2]', 'World', 'string']] #read in from your excel file
result = to_tree([[[*filter(None, a.split('/'))], b, c] for a, b, c in col_data])
print(json.dumps(result, indent=4))

输出:

[
    {
        "tag": "abc",
        "child": [
            {
                "tag": "a[2]",
                "child": [
                    {
                        "tag": "a",
                        "child": [
                            {
                                "tag": "x[1]",
                                "text": "Hello",
                                "type": "string"
                            },
                            {
                                "tag": "x[2]",
                                "text": "World",
                                "type": "string"
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

【讨论】:

  • 干净优雅。奇迹般有效。非常感谢队友!!
  • 如果我需要将 excel 行中的其他列值添加到 JSON 对应的最内层子项中,有什么建议可以添加它们吗?
  • @Parsh 您能否发布新列数据的示例以及最终结果的外观?如果您的第二列值遵循与第一列相同的路径结构,那么您可以将两列合并为一个列表并传递给to_tree,但我不太确定您的第二列值是否真的如此结构化。
  • 不幸的是,它们不遵循相同的分隔符“/”格式。我在问题中包含了一个示例。如果可能,请提供帮助...如果无法将这些其他列的数据与最里面的子项一起添加,您还可以建议任何其他可行的 JSON 结构以有意义的方式显示数据..
  • 这简直太完美了。成就了我的一天。谢谢@Ajax1234 !!
【解决方案2】:
def to_dict(data, old_data=None):
    json={}
    if old_data!=None:
        json["child"]=old_data
    for row in data.split("\n"):
        path=json
        for element in row.strip("/").split("/"):
            if not "child" in path:
                path["child"]=[]
            path=path["child"]
            for path_el in path:
                if element==path_el["tag"]:
                    path=path_el
                    break
            else:
                path.append({"tag":element})
                path=path[-1]
    return json["child"]
#tests:
column="""/abc/a[2]/a/x[1]
/abc/a[2]/a/x[2]"""
print(to_dict_2(column))
print(to_dict_2(column,[{'tag': 'abc', 'child': [{'tag': 'old entry'}]}]))

【讨论】:

  • 谢谢伙计,感谢您的宝贵时间。按预期工作!
  • 好奇的问题:在我的 excel 中,如果第 1 列包含值(行),我将作为“数据”变量传递,我想将 excel 对应的第 2 列的值与每个最里面的子项一起附加(沿JSON 中最后一个“/”之后包含标签的子元素。这是直接可能的还是需要我稍微调整一下代码?
  • @Parsh,我不明白你的问题。
  • 我已经用“附加更新”标题下的示例更新了这个问题。
  • @Parsh,这些数据以什么格式提供给程序?如果是字符串,那么列之间的符号是什么?
猜你喜欢
  • 2019-11-18
  • 2021-12-18
  • 1970-01-01
  • 2012-08-09
  • 1970-01-01
  • 2016-12-27
  • 1970-01-01
  • 2019-08-23
  • 2010-10-19
相关资源
最近更新 更多