Вопрос по python, json, algorithm – Рекурсивная функция для создания иерархического объекта JSON?

8

Я просто недостаточно хороший компьютерщик, чтобы понять это самостоятельно :(

У меня есть API, который возвращает ответы JSON, которые выглядят так:

// call to /api/get/200
{ id : 200, name : 'France', childNode: [ id: 400, id: 500] } 
// call to /api/get/400
{ id : 400, name : 'Paris', childNode: [ id: 882, id: 417] } 
// call to /api/get/500
{ id : 500, name : 'Lyon', childNode: [ id: 998, id: 104] } 
// etc

Я хотел бы проанализировать его рекурсивно и построить иерархический объект JSON, который выглядит примерно так:

{ id: 200,
  name: 'France', 
  children: [
     { id: 400,
       name: 'Paris',
       children: [...]
     },
     { id: 500,
       name: 'Lyon', 
       children: [...]
     } 
  ],
} 

Пока что у меня есть это, которое анализирует каждый узел дерева, но не сохраняет его в объект JSON. Как я могу расширить это, чтобы сохранить его в объект JSON?

hierarchy = {}
def get_child_nodes(node_id):   
    request = urllib2.Request(ROOT_URL + node_id)
    response = json.loads(urllib2.urlopen(request).read())
    for childnode in response['childNode']:
        temp_obj = {}
        temp_obj['id'] = childnode['id']
        temp_obj['name'] = childnode['name']
        children = get_child_nodes(temp_obj['id'])
     // How to save temp_obj into the hierarchy?
get_child_nodes(ROOT_NODE)

Это не домашнее задание, но, возможно, мне нужно сделать домашнее задание, чтобы лучше решить эту проблему :( Спасибо за любую помощь.

попробуйте simplejson.dumps (). fanlix
Список объектов, поэтому иерархия продолжается вплоть до конечных узлов. flossfan
@ Jan-PhilipGehrcke - да, так и должно быть. В настоящее время корневые узлы не сохраняются, я понял. flossfan
это дочерние элементы, содержащие идентификатор или объект? wong2
Не должно ли это бытьresponse['name'] вместоchildnode['name'] в вашем коде? Jan-Philip Gehrcke

Ваш Ответ

5   ответов
-1

Отказ от ответственности: я понятия не имею, что такое json, поэтому вам, возможно, придется разобраться, как правильно написать это на своем языке: с. Если псевдокод в моем примере слишком псевдо, не стесняйтесь спрашивать больше деталей.

Вам нужно что-то вернуть куда-то. Если вы никогда не вернете что-либо в своем рекурсивном вызове, вы не сможете получить ссылку на ваши новые объекты и сохранить ее в тех объектах, которые у вас есть, где вы вызвали рекурсию.

def getChildNodes (node) returns [array of childNodes]
    data = getData(fromServer(forThisNode))
    new childNodes array
    for child in data :
        new temp_obj
        temp_obj.stores(child.interestingStuff)
        for grandchild in getChildN,odes(child) :
            temp_obj.arrayOfchildren.append(grandchild) 
        array.append(temp_obj)
    return array

Кроме того, вы можете использовать итератор вместо возврата, если ваш язык поддерживает это.

2

Вы можете использовать это (более компактная и читаемая версия)

def get_child_nodes(node_id):   
    request = urllib2.Request(ROOT_URL + node_id)
    response = json.loads(urllib2.urlopen(request).read())
    return {
       "id":response['id'],
       "name":response['name'],
       "children":map(lambda childId: get_child_nodes(childId), response['childNode'])
    }

get_child_nodes(ROOT_NODE)
1

Вы не возвращаете ничего при каждом вызове рекурсивной функции. Похоже, вы просто хотите добавить каждыйtemp_obj Словарь в список на каждой итерации цикла, и вернуть его после окончания цикла. Что-то вроде:

def get_child_nodes(node_id):   
    request = urllib2.Request(ROOT_URL + node_id)
    response = json.loads(urllib2.urlopen(request).read())
    nodes = []
    for childnode in response['childNode']:
        temp_obj = {}
        temp_obj['id'] = childnode['id']
        temp_obj['name'] = childnode['name']
        temp_obj['children'] = get_child_nodes(temp_obj['id'])
        nodes.append(temp_obj)
    return nodes

my_json_obj = json.dumps(get_child_nodes(ROOT_ID))

(Кстати, пожалуйста, остерегайтесь смешивания табуляции и пробелов, поскольку Python не очень-то прощает это. Лучше придерживаться только пробелов.)

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededjson.dumps()Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
1

У меня была та же самая проблема сегодня днем, и в итоге я перенастроил некоторый код, который нашел в Интернете.

Я загрузил код в Github (https://github.com/abmohan/objectjson), а также PyPi (https://pypi.python.org/pypi/objectjson/0.1) под названием пакета «objectjson». Вот и она ниже:

Code (Objectjson.py)

import json

class ObjectJSON:

  def __init__(self, json_data):

    self.json_data = ""

    if isinstance(json_data, str):
      json_data = json.loads(json_data)
      self.json_data = json_data

    elif isinstance(json_data, dict):
      self.json_data = json_data

  def __getattr__(self, key):
    if key in self.json_data:
      if isinstance(self.json_data[key], (list, dict)):
        return ObjectJSON(self.json_data[key])
      else:
        return self.json_data[key]
    else:
      raise Exception('There is no json_data[\'{key}\'].'.format(key=key))

  def __repr__(self):
    out = self.__dict__
    return '%r' % (out['json_data'])

Sample Usage

from objectjson import ObjectJSON

json_str = '{ "test": {"a":1,"b": {"c":3} } }'

json_obj = ObjectJSON(json_str)

print(json_obj)           # {'test': {'b': {'c': 3}, 'a': 1}}
print(json_obj.test)      # {'b': {'c': 3}, 'a': 1}
print(json_obj.test.a)    # 1
print(json_obj.test.b.c)  # 3
6
def get_node(node_id):   
    request = urllib2.Request(ROOT_URL + node_id)
    response = json.loads(urllib2.urlopen(request).read())
    temp_obj = {}
    temp_obj['id'] = response['id']
    temp_obj['name'] = response['name']
    temp_obj['children'] = [get_node(child['id']) for child in response['childNode']]
    return temp_obj

hierarchy = get_node(ROOT_NODE)

Похожие вопросы