2012-05-24 15 views
7

io non sono solo un buon informatico abbastanza per capirlo da solo :(Funzione ricorsiva per creare un oggetto JSON gerarchico?

Ho un'API che restituisce risposte JSON che assomigliano a questo:

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

vorrei analizzarlo ricorsivamente e costruire un oggetto JSON gerarchico che sembra qualcosa di simile:

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

Finora, ho questa, che fa analizzare ogni nodo dell'albero, ma non salva in un oggetto JSON Come posso. espandi questo per salvarlo nel JS SU oggetto?

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) 

Questo non è lavoro, ma forse ho bisogno di fare un certo lavoro per ottenere una migliore a risolvere questo tipo di problema :(Grazie per tutto l'aiuto.

+0

è figli dei figli contenenti id o un oggetto? – wong2

+0

Un elenco di oggetti, quindi la gerarchia continua fino ai nodi foglia. – flossfan

+0

prova simplejson.dumps(). – fanlix

risposta

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) 
1

Non stai tornando qualsiasi cosa, da ogni .. chiamata alla funzione ricorsiva Così, sembra che si vuole solo aggiungere ogni dizionario temp_obj in un elenco su ogni iterazione del ciclo, e restituirlo dopo la fine del ciclo Qualcosa di simile:

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

(BTW, per favore attenzione a mescolare tab e spazi come Python non lo è perdonando molto Meglio attenersi a soli spazi.)

+0

E come creeresti la gerarchia desiderata da quella lista? L'obiettivo è quello di avere un insieme annidato di dizionari che sarà quindi 'json.dumps()' ed. –

+0

E in che modo il mio codice non lo ha fornito? Ogni ricorsione forma il proprio dizionario, che viene quindi restituito al genitore. –

+0

Scusami Daniel. Ho letto male sia la struttura desiderata che il codice. –

-1

Disclaimer: Non ho idea di cosa sia JSON, quindi potresti dover risolvere il problema per scriverlo correttamente nella tua lingua: p. Se lo pseudo-codice nel mio esempio è troppo pseudo, non esitare a chiedere maggiori dettagli.

È necessario restituire qualcosa da qualche parte. Se non si restituisce mai qualcosa nella propria chiamata ricorsiva, non è possibile ottenere il riferimento ai nuovi oggetti e memorizzarlo negli oggetti presenti in cui è stata chiamata la ricorsione.

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 getChildNodes(child) : 
      temp_obj.arrayOfchildren.append(grandchild) 
     array.append(temp_obj) 
    return array 

In alternativa, è possibile utilizzare un iteratore anziché un ritorno, se supportato dalla lingua.

2

È possibile utilizzare questo (una versione più compatta e leggibili)

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

Ho avuto lo stesso problema di questo pomeriggio, e ha finito per cambiare canale, un po 'di codice che ho trovato in rete.

Ho caricato il codice su Github (https://github.com/abmohan/objectjson) e PyPi (https://pypi.python.org/pypi/objectjson/0.1) con il nome del pacchetto "objectjson". Eccola qui di seguito così:

Codice (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 dell'uso

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 
Problemi correlati