用Python从字典列表创建分层的JSON转储

9
表格如下:
categories = Table("categories", metadata,
                   Column("id", Integer, primary_key=True),
                   Column("name", String),
                   Column("parent_id", Integer, ForeignKey("categories.id"),
                          CheckConstraint('id!=parent_id'), nullable=True),

)

一个分类可以有很多子类,但只能有一个父类。我使用CTE得到了以下字典值列表: 例如,对于id:14,父类是13,并且从父类8 -> 10 -> 12 -> 13 -> 14进行遍历,其中父类8没有父类id。

[
    {
      "id": 14, 
      "name": "cat14", 
      "parent_id": 13, 
      "path_info": [
        8, 
        10, 
        12, 
        13, 
        14
      ]
    }, 
    {
      "id": 15, 
      "name": "cat15", 
      "parent_id": 13, 
      "path_info": [
        8, 
        10, 
        12, 
        13, 
        15
      ]
    }
  ]

我希望在列表中将父类别的属性嵌入为子类别,如下所示:
{
  "id": 14, 
  "name": "cat14", 
  "parent_id": 13, 
  "subcats": [
       {
         "id: 8", 
         "name": "cat8", 
         "parent_id":null
       }, 
       {
         "id: 10", 
         "name": "cat10", 
         "parent_id":8
       },  
       {
         "id: 12", 
         "name": "cat12", 
         "parent_id":10
       },   
      and similarly for ids 13 and 14..... 
     ]
}, 
{
  "id": 15, 
  "name": "cat15", 
  "parent_id": 13, 
  "subcats": [
       {
         "id: 8", 
         "name": "cat8", 
         "parent_id":null
       }, 
       {
         "id: 10", 
         "name": "cat10", 
         "parent_id":8
       },  
       {
         "id: 12", 
         "name": "cat12", 
         "parent_id":10
       },   
       and similarly for ids 13, 14, 15..... 
     ]
}

请注意,字典中的“path_info”已被删除,并且每个ID都显示了其详细信息。我想要具有以上缩进格式的json转储。如何操作?使用Flask 0.10和Python 2.7。
3个回答

3

有一种可行的方法可以使用几个列表/字典推导式来完成此操作。

lst = [{"id": 14, "name": "cat14", "parent_id": 13, "path_info": [8, 10, 12, 13, 14]}, {"id": 15, "name": "cat15", "parent_id": 13, "path_info": [8, 10, 12, 13, 15]}]

master_dct = { d['id'] : d for d in lst}
for d in lst:
    d['subcats'] = [{field : master_dct[i][field] for field in ['id', 'name', 'parent_id']} \
        for i in d['path_info'] if i in master_dct]

import json
with open('out.json', 'w') as f:
    json.dump(lst, f)

1
你可以在Python代码中执行它:
假设我们有一个JSON对象。我稍微修改了它 - 添加了缺失的节点并将其包装到对象中,因为规范要求如此:
    {
      "array": [
          {
            "id": 14, 
            "name": "cat14", 
            "parent_id": 13, 
            "path_info": [
              8, 
              10, 
              12, 
              13, 
              14
            ]
          }, 
          {
            "id": 15, 
            "name": "cat15", 
            "parent_id": 13, 
            "path_info": [
              8, 
              10, 
              12, 
              13, 
              15
            ]
          },
          {
            "id": 13, 
            "name": "cat13", 
            "parent_id": 12, 
            "path_info": [
              8, 
              10, 
              12, 
              13
            ]
          },
         {
            "id": 12, 
            "name": "cat12", 
            "parent_id": 10, 
            "path_info": [
              8, 
              10, 
              12
            ]
          }, 
          {
            "id": 10, 
            "name": "cat10", 
            "parent_id": 8, 
            "path_info": [
              8, 
              10
            ]
          },
          {
            "id": 8, 
            "name": "cat8", 
            "parent_id": null, 
            "path_info": [
              8
            ]
          }
        ]
    }

然后您可以使用以下代码:
    # load data above from file
    j=json.load(open('json_file_above.json'))   # 

    #  the array with real data we need
    a=j['array']  

    # auxiliary dict which have node identificators as keys and nodes as values
    d={x['id']:x for x in a}  

    # here the magic begins :)
    for x in a:
       # add new key with list to each element
       x['subcats'] = [ 
                       # compose dict element for subcats
                       dict(id=i, name=d[i]['name'], parent_id=d[i]['parent_id'])
                       for 
                       i 
                       in [
                           # we take path_info id list and
                           # cut off the first element - itself
                           y for y in x['path_info'][1:]
                          ]  
                      ]
       del x['path_info']

确保你得到你所需的东西:

    >>> print(json.dumps(a, indent=True))
    [
     {
      "name": "cat14",
      "subcats": [
       {
        "name": "cat10",
        "id": 10,
        "parent_id": 8
       },
       {
        "name": "cat12",
        "id": 12,
        "parent_id": 10
       },
       {
        "name": "cat13",
        "id": 13,
        "parent_id": 12
       },
       {
        "name": "cat14",
        "id": 14,
        "parent_id": 13
       }
      ],
      "id": 14,
      "parent_id": 13
     },
     {
      "name": "cat15",
      "subcats": [
       {
        "name": "cat10",
        "id": 10,
        "parent_id": 8
       },
       {
        "name": "cat12",
        "id": 12,
        "parent_id": 10
       },
       {
        "name": "cat13",
        "id": 13,
        "parent_id": 12
       },
       {
        "name": "cat15",
        "id": 15,
        "parent_id": 13
       }
      ],
      "id": 15,
      "parent_id": 13
     },
     {
      "name": "cat13",
      "subcats": [
       {
        "name": "cat10",
        "id": 10,
        "parent_id": 8
       },
       {
        "name": "cat12",
        "id": 12,
        "parent_id": 10
       },
       {
        "name": "cat13",
        "id": 13,
        "parent_id": 12
       }
      ],
      "id": 13,
      "parent_id": 12
     },
     {
      "name": "cat12",
      "subcats": [
       {
        "name": "cat10",
        "id": 10,
        "parent_id": 8
       },
       {
        "name": "cat12",
        "id": 12,
        "parent_id": 10
       }
      ],
      "id": 12,
      "parent_id": 10
     },
     {
      "name": "cat10",
      "subcats": [
       {
        "name": "cat10",
        "id": 10,
        "parent_id": 8
       }
      ],
      "id": 10,
      "parent_id": 8
     },
     {
      "name": "cat8",
      "subcats": [],
      "id": 8,
      "parent_id": null
     }
    ]
    >>>

1
这是相应的Python代码:简单明了。
import json
categories = [] #input
def transform(category, child_node_id):
    category['subcats'].append({
       'id': child_node_id,
       'name': 'cat%s' % child_node_id,
       'parent_id': category['id']
    })


for category in categories:
    category['subcats'] = []
    [transform(category, child_node_id) for child_node_id in category['path_info']]
    category.pop('path_info', None)

print(json.dumps(categories, indent=4))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接