10

I'm just not a good enough computer scientist to figure this out by myself :(

I have an API that returns JSON responses that look like this:

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

I would like to parse it recursively and build a hierarchical JSON object that looks something like this:

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

So far, I have this, which does parse every node of the tree, but doesn't save it into a JSON object. How can I expand this to save it into the JSON object?

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)

This isn't homework, but maybe I need to do some homework to get better at solving this kind of problem :( Thank you for any help.

5
  • is children's children containing id or object? Commented May 24, 2012 at 12:19
  • A list of objects, so the hierarchy continues all the way down to the leaf nodes. Commented May 24, 2012 at 12:24
  • Shouldn't this be response['name'] instead of childnode['name'] in your code? Commented May 24, 2012 at 12:37
  • @Jan-PhilipGehrcke - yes it should. Currently the root nodes aren't being stored, I've realised. Commented May 24, 2012 at 12:47
  • why do the questions and answers contain request from the urllib2? Is it coz the data that is handled is on a website? Commented Jul 17, 2015 at 9:25

5 Answers 5

7
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)
Sign up to request clarification or add additional context in comments.

Comments

2

You could use this (a more compact and readable version)

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)

Comments

1

You're not returning anything from each call to the recursive function. So, it seems like you just want to append each temp_obj dictionary into a list on each iteration of the loop, and return it after the end of the loop. Something like:

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, please beware of mixing tabs and spaces as Python isn't very forgiving of that. Best to stick to just spaces.)

3 Comments

And how would you create the desired hierarchy from that list? The goal is to have a nested set of dictionaries which will then be json.dumps()ed.
And how has my code not provided that? Each recursion forms its own dictionary, which is then returned to the parent.
Excuse me Daniel. I misread both the desired structure and your code.
1

I had the same problem this afternoon, and ended up rejigging some code I found online.

I've uploaded the code to Github (https://github.com/abmohan/objectjson) as well as PyPi (https://pypi.python.org/pypi/objectjson/0.1) under the package name 'objectjson'. Here it is below, as well:

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

Comments

-1

Disclaimer : I have no idea what json is about, so you may have to sort out how to write it correctly in your language :p. If the pseudo-code in my example is too pseudo, feel free to ask more details.

You need to return something somewhere. If you never return something in your recursive call, you can't get the reference to your new objects and store it in the objects you have where you called the recursion.

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

Alternatively, you can use an iterator instead of a return, if your language supports it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.