Decoding JSON with Python and storing nested object - python

I am trying to decode the following JSON file with Python:
{"node":[
{
"id":"12387",
"ip":"172.20.0.1",
"hid":"213",
"coord":{"dist":"12","lat":"-9.8257","lon":"65.0880"},
"status":{"speed":"90","direction":"N"},
"ts":"12387"}
]
}
By using:
json_data=open('sampleJSON')
jdata = json.load(json_data)
for key, value in jdata.iteritems():
print "Key:"
print key
print "Value:"
print value
and i have as output:
Key:
node
Value:
[{u'status': {u'direction': u'N', u'speed': u'90'}, u'ip': u'172.20.0.1', u'ts': u'12387', u'coord': {u'lat': u'-9.8257', u'lon': u'65.0880', u'dist': u'12'}, u'hid': u'213', u'id': u'12387'}]
And i want to be able to print the key's and values of the nested objects status, coord, and also que key/values of node, "hid", "id", "ip" and "ts".
How can i interate throughout all the nested values?
Thank you in advance!

You can use a recursive function to print it all out. This could be improved, but here is the idea:
import json
json_data = open('data.json')
jdata = json.load(json_data)
def printKeyVals(data, indent=0):
if isinstance(data, list):
print
for item in data:
printKeyVals(item, indent+1)
elif isinstance(data, dict):
print
for k, v in data.iteritems():
print " " * indent, k + ":",
printKeyVals(v, indent + 1)
else:
print data
OUTPUT
node:
status:
direction: N
speed: 90
ip: 172.20.0.1
ts: 12387
coord:
lat: -9.8257
lon: 65.0880
dist: 12
hid: 213
id: 12387
Otherwise, you could just use:
import pprint
pprint.pprint(jdata)

Without knowing more about your specific use case, it's hard to give a general answer, but..
If you have an arbitrarily nested structure, this is a good case for recursion.
simple sample code:
def print_object(object, indent=0):
if type(object)==dict:
for key, value in object.iteritems():
print " "*4*indent, "Key: ", key
print " "*4*indent, "Value: "
print_object(value, indent+1)
elif type(object)==list:
for value in object:
print_object(value,indent+1)
else:
print " "*4*indent, object
you really don't want to do strict type checking, but it works for quick-and-dirty sample code.
output:
Key: node
Value:
Key: status
Value:
Key: direction
Value:
N
Key: speed
Value:
90
Key: ip
Value:
172.20.0.1
Key: ts
Value:
12387
Key: coord
Value:
Key: lat
Value:
-9.8257
Key: lon
Value:
65.0880
Key: dist
Value:
12
Key: hid
Value:
213
Key: id
Value:
12387

It looks like the top level element of your JSON is a dictionary containing a list of dictionaries. If you want to keep this structure, try the code below.
from pprint import pprint
json_data=open('sampleJSON')
jdata = json.load(json_data)
node = jdata['node'][0]
for key, value in node.iteritems():
pprint("Key:")
pprint(key)
pprint("Value:")
pprint(value)

Related

How to format JSON item OrderedDic dumps with substrings-PYTHON 3

I am trying to convert a Json file that looks like
{
# "item_1":"value_11",
# "item_2":"value_12",
# "item_3":"value_13",
# "item_4":["sub_value_14", "sub_value_15"],
# "item_5":{
# "sub_item_1":"sub_item_value_11",
# "sub_item_2":["sub_item_value_12", "sub_item_value_13"]
# }
# }
TO something that looks like this:
{
# "node_item_1":"value_11",
# "node_item_2":"value_12",
# "node_item_3":"value_13",
# "node_item_4_0":"sub_value_14",
# "node_item_4_1":"sub_value_15",
# "node_item_5_sub_item_1":"sub_item_value_11",
# "node_item_5_sub_item_2_0":"sub_item_value_12",
# "node_item_5_sub_item_2_0":"sub_item_value_13"
# }
I am aware that you can't maintain the order of the Json file when converted to CSV. I am considering to do a workaround by loading the JSON data into OrderedDic objects (which cause them to be added in the order that the input document lists them. However, I am new to working with JSON files, as well as OrderedDic function.
To split items into subgroups i used:
def reduce_item(key, value):
global reduced_item
#Reduction Condition 1
if type(value) is list:
i=0
for sub_item in value:
reduce_item(key+'_'+to_string(i), sub_item)
i=i+1
#Reduction Condition 2
elif type(value) is dict:
sub_keys = value.keys()
for sub_key in sub_keys:
reduce_item(key+'_'+to_string(sub_key), value[sub_key])
#Base Condition
else:
reduced_item[to_string(key)] = to_string(value)
But how do I use the orderedDic along with the above code to show this output:
{
# "node_item_1":"value_11",
# "node_item_2":"value_12",
# "node_item_3":"value_13",
# "node_item_4_0":"sub_value_14",
# "node_item_4_1":"sub_value_15",
# "node_item_5_sub_item_1":"sub_item_value_11",
# "node_item_5_sub_item_2_0":"sub_item_value_12",
# "node_item_5_sub_item_2_0":"sub_item_value_13"
# }
I have the below code as well but it does not split each in subgroups based on the conditions of the subtring code above:
import json
from collections import OrderedDict
with open("/home/file/official.json", 'r') as fp:
metrics_types = json.load(fp, object_pairs_hook=OrderedDict)
print(metrics_types)
That shows:
Any suggestions?
You can use a function that iterates through the given dict or list items and merges the keys from the dict output of the recursive calls:
def flatten(d):
if not isinstance(d, (dict, list)):
return d
out = {}
for k, v in d.items() if isinstance(d, dict) else enumerate(d):
f = flatten(v)
if isinstance(f, dict):
out.update({'%s_%s' % (k, i): s for i, s in f.items()})
else:
out[k] = f
return out
so that given:
d = {
"item_1":"value_11",
"item_2":"value_12",
"item_3":"value_13",
"item_4":["sub_value_14", "sub_value_15"],
"item_5":{
"sub_item_1":"sub_item_value_11",
"sub_item_2":["sub_item_value_12", "sub_item_value_13"]
}
}
flatten(d) returns:
{'item_1': 'value_11',
'item_2': 'value_12',
'item_3': 'value_13',
'item_4_0': 'sub_value_14',
'item_4_1': 'sub_value_15',
'item_5_sub_item_1': 'sub_item_value_11',
'item_5_sub_item_2_0': 'sub_item_value_12',
'item_5_sub_item_2_1': 'sub_item_value_13'}
The above assumes that you're using Python 3.7 or later, where dict keys are guaranteed to be ordered. If you're using earlier versions, you can use OrderedDict in place of a regular dict.

Print statement not printing anything on console in python

Print statement not printing anything on console in python.
I am printing the key, value of the JSON file where the key starts with #id
found = False
for key, di in json.loads(json_data).iteritems():
for k, v in di.items():
if k.startswith('#id'):
found = True
print k, v
sys.stout.flush()
break
if found:
break
I think have done a mistake. Any help will be appreciated.
Given the sample data you provided in the comment section, you can try this:
import json
json_data = '{ "nvd": { "entry": [ { "#id": "CVE-2016-0001", "vuln:cve-id": "CVE-2016-0001", "vuln:published-datetime": "2017-05-11T10:29:55.767-04:00", "vuln:last-modified-datetime": "2017-05-11T10:29:55.767-04:00", "vuln:summary": "** REJECT ** DO NOT USE THIS CANDIDATE NUMBER. " }]}}'
wantedKey = "#id"
found = False
for key, di in json.loads(json_data).items():
if wantedKey in di['entry'][0]:
found = True
print(wantedKey + " : " + di['entry'][0][wantedKey])
break
Output:
#id : CVE-2016-0001

Create a file 'path like string' from a Python Dictionary

I found a method to iterate a python dictionary object recursively on this forum. However, I wish to extend that function so that I get a string similar to the structure of a file path. With my function below, I expect an output in the form of
/key1/value1
/key2/value2
/key3/key3a/value3a
/key4/key4a/key4a1/value4a1
/key4/key4a/key4a2/value4a2
/key4/key4a/key4a3/value4a3
/key4/key4b/key4b1/key4b1a/value4b1a
/key4/key4b/key4b1/key4b1b/value4b1b
/key4/key4b/key4b1/key4b1c/value4b1c
/key4/key4c/key4c1/key4c1a/value4c1a
/key4/key4c/key4c1/key4c1b/value4c1b
/key4/key4c/key4c1/key4c1c/value4c1c
Unfortunately, I hit a block. I cannot figure out how to achieve that. Below is the code that I came up with. Any help is greatly appreciated.
import sys
import collections
dict_object = {
'key1': 'value1',
'key2': 'value2',
'key3': {'key3a': 'value3a'},
'key4': {
'key4a': {
'key4a1': 'value4a1',
'key4a2': 'value4a2',
'key4a3': 'value4a3'
},
'key4b': {
'key4b1': {
'key4b1a': 'value4b1a',
'key4b1b': 'value4b1b',
'key4b1c': 'value4b1c'
},
'key4c': {
'key4c1': {
'key4c1a': 'value4c1a',
'key4c1b': 'value4c1b',
'key4c1c': 'value4c1c'
}
}
}
}
}
def print_dict(dictionary, path='', parent=''):
""" This finction recursively prints nested dictionaries."""
#Sort the dictionary object by its keys
if isinstance(dictionary, dict):
dictionary = collections.OrderedDict(sorted(dictionary.items()))
else:
dictionary = sorted(dictionary.items(), key=operator.itemgetter(1))
#iterate each sorted dictionary key
for key, value in dictionary.iteritems():
if isinstance(value, dict):
path = ''
path = '%s/%s/%s' % (path, parent, key)
#Repeat this funtion for nested {} instances
print_dict(value, path, key)
else:
#Print the last node i.e PATH + KEY + VALUE
print '%s/%s/%s' % (path, key, value)
if __name__ == '__main__':
print_dict(dict_object)
Your function appears overly complicated. Only actually print when you have an object that's not a dictionary, otherwise recurse for all values in a dictionary. I simplified path handling to just one string:
def print_dict(ob, path=''):
if not isinstance(ob, dict):
print '{}/{}'.format(path, ob)
else:
for key, value in sorted(ob.items()):
print_dict(value, '{}/{}'.format(path, key))
I didn't bother with creating OrderedDict objects; all you need is iteration in sorted order.
This produces the expected output:
>>> print_dict(dict_object)
/key1/value1
/key2/value2
/key3/key3a/value3a
/key4/key4a/key4a1/value4a1
/key4/key4a/key4a2/value4a2
/key4/key4a/key4a3/value4a3
/key4/key4b/key4b1/key4b1a/value4b1a
/key4/key4b/key4b1/key4b1b/value4b1b
/key4/key4b/key4b1/key4b1c/value4b1c
/key4/key4b/key4c/key4c1/key4c1a/value4c1a
/key4/key4b/key4c/key4c1/key4c1b/value4c1b
/key4/key4b/key4c/key4c1/key4c1c/value4c1c

Convert python dictionary to JavaScript object literal

Using json.dumps I can convert a dictionary to json format like this:
>>> from json import dumps
>>> dumps({'height': 100, 'title': 'some great title'})
'{"title": "some great title", "height": 100}'
However, I'm looking to turn my dictionary into a javascript literal, like this:
{title: "some great title", height: 100}
(Notice there are no double quotes around title and height.)
Is there a Python library to do this?
If you know all your keys are valid tokens you can use this simple code:
import json
def js_list(encoder, data):
pairs = []
for v in data:
pairs.append(js_val(encoder, v))
return "[" + ", ".join(pairs) + "]"
def js_dict(encoder, data):
pairs = []
for k, v in data.iteritems():
pairs.append(k + ": " + js_val(encoder, v))
return "{" + ", ".join(pairs) + "}"
def js_val(encoder, data):
if isinstance(data, dict):
val = js_dict(encoder, data)
elif isinstance(data, list):
val = js_list(encoder, data)
else:
val = encoder.encode(data)
return val
encoder = json.JSONEncoder(ensure_ascii=False)
js_val(encoder, {'height': 100, 'title': 'some great title'})
The return value of js_val() is in your desired format.
Dirty hack, but could work: subclass JSONEncoder and override _iterencode_dict method, so that it yields key formatted as you want. In python3.3 it is in line 367 of json.encoder module in line yield _encoder(key). You probably want to copy the whole method and change this line to something like yield key if isinstance(key, str) else _encoder(key).
Again - this is really dirty, unless you have no other option - don't do that. Though, it is doable, what is worth knowing if you really need it.

python: serialize a dictionary into a simple html output

using app engine - yes i know all about django templates and other template engines.
Lets say i have a dictionary or a simple object, i dont know its structure and i want to serialize it into html.
so if i had
{'data':{'id':1,'title':'home','address':{'street':'some road','city':'anycity','postal':'somepostal'}}}
want i want is that rendered in some form of readable html using lists or tables;
data:
id:1
title:home
address:
street: some road
city: anycity
postal:somepostal
now i know i can do
for key in dict.items
print dict[key]
but that wont dive into the child values and list each key, value pair when the key/value is a dictionary - ie the address dict.
Is their a module for python that is lightweight/fast that will do this nicely. or does anyone have any simple code they can paste that might do this.
Solution
All the solutions here were useful. pprint is no doubt the more stable means of printing the dictionary, though it falls short of returning anything near html. Though still printable.
I ended up with this for now:
def printitems(dictObj, indent=0):
p=[]
p.append('<ul>\n')
for k,v in dictObj.iteritems():
if isinstance(v, dict):
p.append('<li>'+ k+ ':')
p.append(printitems(v))
p.append('</li>')
else:
p.append('<li>'+ k+ ':'+ v+ '</li>')
p.append('</ul>\n')
return '\n'.join(p)
It converts the dict into unordered lists which is ok for now. some css and perhaps a little tweaking should make it readable.
Im going to reward the answer to the person that wrote the above code, i made a couple of small changes as the unordered lists were not nesting. I hope all agree that many of the solutions offered proved useful, But the above code renders a true html representation of a dictionary, even if crude.
The example made by pyfunc could easily be modified to generate simple nested html lists.
z = {'data':{'id':1,'title':'home','address':{'street':'some road','city':'anycity','postal':'somepostal'}}}
def printItems(dictObj, indent):
print ' '*indent + '<ul>\n'
for k,v in dictObj.iteritems():
if isinstance(v, dict):
print ' '*indent , '<li>', k, ':', '</li>'
printItems(v, indent+1)
else:
print ' '*indent , '<li>', k, ':', v, '</li>'
print ' '*indent + '</ul>\n'
printItems(z,0)
Not terribly pretty of course, but somewhere to start maybe. If all you want to do is visualize data, the pprint module really is good enough. You could just use the "pre" tag on the result from pprint and put that on your web page.
the pprint version would look something like this:
import pprint
z = {'data':{'id':1,'title':'home','address':{'street':'some road','city':'anycity','postal':'somepostal'}}}
print '<pre>', pprint.pformat(z), '</pre>'
And the html output look something like this:
{'data': {'address': {'city': 'anycity',
'postal': 'somepostal',
'street': 'some road'},
'id': 1,
'title': 'home'}}
Which isn't that pretty, but it at least shows the data in a more structured way.
import pprint
pprint.pprint(yourDict)
Well, no HTML, but similar to your for/print approach.
EDIT: or use:
niceText = pprint.pformat(yourDict)
this will give you the same nice output with all indents, etc. Now you can iterate over lines and format it into HTML:
htmlLines = []
for textLine in pprint.pformat(yourDict).splitlines():
htmlLines.append('<br/>%s' % textLine) # or something even nicer
htmlText = '\n'.join(htmlLines)
Here's my simple solution, It can handle any level of nested dictionary.
import json
temp_text = {'decision': {'date_time': None, 'decision_type': None},
'not_received': {'date_time': '2019-04-15T19:18:43.825766'},
'received': {'date_time': None},
'rfi': {'date_time': None},
'under_review': {'date_time': None}}
dict_text_for_html = json.dumps(
temp_text, indent=4
).replace(' ', '&nbsp').replace(',\n', ',<br>').replace('\n', '<br>')
html view of python dict
I needed something similar, but also wanted to pretty print lists, and lists inside the dict. Here's what I came up:
def format(self, obj, indent = 1):
if isinstance(obj, list):
htmls = []
for k in obj:
htmls.append(self.format(k,indent+1))
return '[<div style="margin-left: %dem">%s</div>]' % (indent, ',<br>'.join(htmls))
if isinstance(obj, dict):
htmls = []
for k,v in obj.iteritems():
htmls.append("<span style='font-style: italic; color: #888'>%s</span>: %s" % (k,self.format(v,indent+1)))
return '{<div style="margin-left: %dem">%s</div>}' % (indent, ',<br>'.join(htmls))
return str(obj)
Then, if you're using webapp on appengine, you can just do the following:
self.response.out.write(self.format(obj))
This is an example of the output:
Look at my implementation:
def pretty_items(r, d, nametag="<strong>%s: </strong>", itemtag='<li>%s</li>',
valuetag="%s", blocktag=('<ul>', '</ul>')):
if isinstance(d, dict):
r.append(blocktag[0])
for k, v in d.iteritems():
name = nametag % k
if isinstance(v, dict) or isinstance(v, list):
r.append(itemtag % name)
pretty_items(r, v)
else:
value = valuetag % v
r.append(itemtag % (name + value))
r.append(blocktag[1])
elif isinstance(d, list):
r.append(blocktag[0])
for i in d:
if isinstance(i, dict) or isinstance(i, list):
r.append(itemtag % " - ")
pretty_items(r, i)
else:
r.append(itemtag % i)
r.append(blocktag[1])
Will output all items in HTML format using <ul> and <li> tags. And is also optional to change the tags. And then, just use CSS to handle with the indentation.
None of the above examples give good results, so I wrote two of my own functions that create beautiful looking html output for dictionaries.
def dict_to_html(dd, level=0):
"""
Convert dict to html using basic html tags
"""
import simplejson
text = ''
for k, v in dd.iteritems():
text += '<br>' + ' '*(4*level) + '<b>%s</b>: %s' % (k, dict_to_html(v, level+1) if isinstance(v, dict) else (simplejson.dumps(v) if isinstance(v, list) else v))
return text
def dict_to_html_ul(dd, level=0):
"""
Convert dict to html using ul/li tags
"""
import simplejson
text = '<ul>'
for k, v in dd.iteritems():
text += '<li><b>%s</b>: %s</li>' % (k, dict_to_html_ul(v, level+1) if isinstance(v, dict) else (simplejson.dumps(v) if isinstance(v, list) else v))
text += '</ul>'
return text
You could use pretty print (pprint)
or if you want to do some further processing of display then you have to run through the dict yourself.
Be warned that the code is crude and will require numerous refinements. Solution uses recursion too, which is bad, if the recursion depth is higher.
z = {'data':{'id':1,'title':'home','address':{'street':'some road','city':'anycity','postal':'somepostal', 'telephone':{'home':'xxx','offie':'yyy'}}}}
def printItems(dictObj, indent):
it = dictObj.iteritems()
for k,v in it:
if isinstance(v, dict):
print ' '*indent , k, ':'
printItems(v, indent+1)
else:
print ' '*indent , k, ':', v
printItems(z,0)
Output:
data :
address :
city : anycity
postal : somepostal
street : some road
telephone :
home : xxx
offie : yyy
id : 1
title : home
Here is my version with support of lists (labels are verbose names of keys in dictionary):
def render_value(value, labels):
if isinstance(value, (list, tuple)):
return render_list(value, labels)
elif isinstance(value, dict):
return render_dict(value, labels)
else:
return value
def render_list(lst, labels):
items = [
'<li>%s</li>' % render_value(value, labels)
for value in lst
]
return '\n'.join(['\n<ul>'] + items + ['</ul>\n'])
def render_dict(dct, labels):
items = []
for key, value in dct.items():
if not value: continue
key = labels.get(key, key)
value = render_value(value, labels)
items.append('<li><b>%s</b>: %s</li>' % (key, value))
return '\n'.join(['\n<ul>'] + items + ['</ul>\n'])
imagine we have this :{name: "a", children:[{name: "b", children: [] },{..},{..}]
def ConvertDictToUlLi():
jsonResult = GetSomeRecursiveDict()
def CreateHtml(DictItem, output):
output = "<li>"+DictItem["name"] if jsonResult.has_key("name") else " "
if len(DictItem["children"]) > 0:
output = output + "<ul>"
for item in DictItem["children"]:
output = output + " "+CreateHtml(item, output)+" "
output = output + "</ul>"
return output+"</li>"
result = "<ul class='tree'>"+CreateHtml(jsonResult, "")+"</ul>"
return result

Categories