Восстановите иерархию папок в формате JSON из MySQL, используя Python - PullRequest
2 голосов
/ 10 июня 2019

У меня есть таблица со структурой, подобной этой:

| itemID |   parentFolderID | folderName

     1              0           folderA
     2              1           folderB
     3              1           folderC
     4              3           folderD
     5              4           folderE
     6              5           file.txt

Разработчику внешнего интерфейса необходимо, чтобы я создал файл JSON с иерархией, представляющей структуру папок, и выглядел следующим образом:

{"name": "folderA",
 "itemID": "1",
 "children":[
       { "name": "folderB",
          "itemID": "2",
          "children": []
       },
       { "name": "folderC",
         "itemID": "3",
         "children": [
               { "name": "folderD",
                 "itemID": "4",
                 "children": [
                       {"name": "folderE",
                        "itemID": "5",
                        "children": [
                               {"name": "file.txt",
                                "itemID": "6"
                               },
                           ]
                        }
                     ]
                  }
               ]
            }
         ]
      }

Я совершенно новичок в базах данных и Python, и эта проблема немного серьезна для моего уровня квалификации.Я посмотрел в CTE, но это не доступно в MySql 5.6.Мне также сказали, что Python лучше справляется с этой задачей, чем пытаться выполнить ее в базе данных.

Я видел предложенные решения, но это либо JS, R, либо что-то еще.Может быть, это работает, но мой вопрос к Python;должен быть способ сделать это.

Как взять таблицу и преобразовать ее в структуру JSON?Спасибо.

Добавление структуры данных Python для запроса MySQL:

 [{'assetID': 1,
  'assetName': 'Study Name',
  'assetTypeID': 2,
  'assetStoreName': 'TEST TEMPLATE',
  'parentAssetID': None},
 {'assetID': 2, 'assetName': '1.json', 'assetTypeID': 1, 'parentAssetID': 1},
 {'assetID': 3,
  'assetName': 'Binder-IRB',
  'assetTypeID': 2,
  'assetStoreName': 'TEST TEMPLATE',
  'parentAssetID': 1},
 {'assetID': 4,
  'assetName': 'Serverless Security Evaluation Criteria 2019.pdf',
  'assetTypeID': 1,
  'assetStoreName': 'TEST TEMPLATE',
  'parentAssetID': 1},
 {'assetID': 5,
  'assetName': '1- IRB Approvals',
  'assetTypeID': 2,
  'assetStoreName': 'TEST TEMPLATE',
  'parentAssetID': 3},
 {'assetID': 6, 'assetName': '2-ICF', 'assetTypeID': 2, 'parentAssetID': 3},
 {'assetID': 7,
  'assetName': "3-Reports",
  'assetTypeID': 2,
  'assetStoreName': 'TEST TEMPLATE',
  'parentAssetID': 3},
 {'assetID': 8,
  'assetName': 'sample resume.docx',
  'assetTypeID': 1,
  'assetStoreName': 'TEST TEMPLATE',
  'parentAssetID': 5},
 {'assetID': 9,
  'assetName': 'Inactive ICFs',
  'assetTypeID': 2,
  'assetStoreName': 'TEST TEMPLATE',
  'parentAssetID': 6}]

Ответы [ 2 ]

2 голосов
/ 10 июня 2019

Вот решение, использующее ваши данные в переменной с меткой query:

def find_and_add_child(dic, element):
    """
    Searches through the passed in dict and its children
    to find where to insert `element`. Returns True if
    inserted and False otherwise. (Recursive)
    """
    if dic['itemID'] == element['parentAssetID']:
        # This is the right parent so add the child
        dic['children'].append({
            "name": element['assetName'],
            "itemID": element['assetID'],
            "children": []
        })
        return True
    else: # Search the children to find a valid parent
        for child in dic['children']:
            if find_and_add_child(child, element):
                return True
        return False

def query_to_json(query):
    """
    Converts the passed in json as a list of dicts
    to a json object.
    """
    results = []
    for entry in query:
        if entry['parentAssetID'] == None:
            # If not parent ID
            results.append({
                "name": entry['assetName'],
                "itemID": entry['assetID'],
                "children":[]
            })
        else: # We need to find the parent
            for result in results:
                if find_and_add_child(result, entry):
                    break # Entry added so break out of this loop
    return results

import json
print(json.dumps(query_to_json(query), indent=2))

Выход:

[
  {
    "name": "Study Name",
    "itemID": 1,
    "children": [
      {
        "name": "1.json",
        "itemID": 2,
        "children": []
      },
      {
        "name": "Binder-IRB",
        "itemID": 3,
        "children": [
          {
            "name": "1- IRB Approvals",
            "itemID": 5,
            "children": [
              {
                "name": "sample resume.docx",
                "itemID": 8,
                "children": []
              }
            ]
          },
          {
            "name": "2-ICF",
            "itemID": 6,
            "children": [
              {
                "name": "Inactive ICFs",
                "itemID": 9,
                "children": []
              }
            ]
          },
          {
            "name": "3-Reports",
            "itemID": 7,
            "children": []
          }
        ]
      },
      {
        "name": "Serverless Security Evaluation Criteria 2019.pdf",
        "itemID": 4,
        "children": []
      }
    ]
  }
]
0 голосов
/ 10 июня 2019

Я бы использовал два слова: во-первых, чтобы фактически реализовать структуру файла; во-вторых, для хранения ссылок на каждый диктовку, которая составляет первое. Допустим, ваша структура данных Python dataframe:

file_structure = {}
dicts = {}
for entry in dataframe:
    # construct initial filestructure for this new entry
    new_dict = {"name": entry["assetName"], "itemID": entry["assetID"]}
    if entry["assetTypeID"] == 2:  # shorthand for checking "is this a folder"
        new_dict["children"] = []
    # assign the new entry to dicts, so we can keep track of it more easily
    dicts[itemID] = new_dict
    # add it as a child to its parent element, or make it the root if necessary
    if entry["parentAssetID"]:
        dicts[entry["parentAssetID"]]["children"].append(new_dict)
    else:
        file_structure = new_dict

Обратите внимание, что file_structure - это то, что сохраняет фактическую структуру, но мы используем dicts для хранения столько ссылок на местоположения в этой файловой структуре, сколько нам нужно. Например, dicts[2] и file_structure["children"][0] относятся к одному и тому же объекту в памяти.

Если есть несколько вещей с ключом None, вы могли бы также рассмотреть вопрос о создании file_structure списка диктов в первую очередь вместо единственного, который есть в вашем примере, и делает file_structure.append(new_dict) вместо file_structure = new_dict.

После всего этого преобразование его в json тривиально:

import json
...
json_str = json.dumps(file_structure)
with open("hierarchy.json", "w") as outfile:
    outfile.write(json_str)
...