You split your problem into two steps. Reading and writing. In the first step you can check if `Aux``is in the keys already. If not you add it. Then you simply open the file to write and write the cleaned data to it:
import json
with open("record.json", "r") as infile:
data = json.load(infile)
for genre in data:
for movie_genre in data[genre]:
if "Aux" not in data[genre][movie_genre].keys():
data[genre][movie_genre]["Aux"] = {"director": "MR J", "Producer": "Mr K"}
with open("record.json", "w") as outfile:
outfile.write(json.dumps(data, indent=2))
Answer from k-nut on Stack OverflowYou split your problem into two steps. Reading and writing. In the first step you can check if `Aux``is in the keys already. If not you add it. Then you simply open the file to write and write the cleaned data to it:
import json
with open("record.json", "r") as infile:
data = json.load(infile)
for genre in data:
for movie_genre in data[genre]:
if "Aux" not in data[genre][movie_genre].keys():
data[genre][movie_genre]["Aux"] = {"director": "MR J", "Producer": "Mr K"}
with open("record.json", "w") as outfile:
outfile.write(json.dumps(data, indent=2))
You can check whether Aux is available in JSON dictionary, if not, you can add it:
try:
json_file = ('record.json')
with open(json_file,'r+') as data_file:
data = json.load(data_file)
if 'Aux' not in data:
data['Movies']['Action']['Aux'] = {"director": "MR J", "Producer": "Mr K"}
except Exception, e:
print e
As I said in my other answer, I don't think there is a way of finding all values associated with the "P1" key without iterating over the whole structure. However I've come up with even better way to do that which came to me while looking at @Mike Brennan's answer to another JSON-related question How to get string objects instead of Unicode from JSON?
The basic idea is to use the object_hook parameter that json.loads() accepts just to watch what is being decoded and check for the sought-after value.
Note: This will only work if the representation is of a JSON object (i.e. something enclosed in curly braces {}), as in your sample.
from __future__ import print_function
import json
def find_values(id, json_repr):
results = []
def _decode_dict(a_dict):
try:
results.append(a_dict[id])
except KeyError:
pass
return a_dict
json.loads(json_repr, object_hook=_decode_dict) # Return value ignored.
return results
json_repr = '{"P1": "ss", "Id": 1234, "P2": {"P1": "cccc"}, "P3": [{"P1": "aaa"}]}'
print(find_values('P1', json_repr))
(Python 3) output:
['cccc', 'aaa', 'ss']
I had the same issue just the other day. I wound up just searching through the entire object and accounted for both lists and dicts. The following snippets allows you to search for the first occurrence of a multiple keys.
import json
def deep_search(needles, haystack):
found = {}
if type(needles) != type([]):
needles = [needles]
if type(haystack) == type(dict()):
for needle in needles:
if needle in haystack.keys():
found[needle] = haystack[needle]
elif len(haystack.keys()) > 0:
for key in haystack.keys():
result = deep_search(needle, haystack[key])
if result:
for k, v in result.items():
found[k] = v
elif type(haystack) == type([]):
for node in haystack:
result = deep_search(needles, node)
if result:
for k, v in result.items():
found[k] = v
return found
deep_search(["P1", "P3"], json.loads(json_string))
It returns a dict with the keys being the keys searched for. Haystack is expected to be a Python object already, so you have to do json.loads before passing it to deep_search.
Any comments for optimization are welcomed!
Parse out the JSON with the json module, which gives you a Python data structure.
Then loop over the 'test' key and dump each dictionary in that list to a new JSON file:
import json
with open(inputjsonfile, 'r') as ifh:
data = json.load(ifh)
for i, entry in enumerate(data['test']):
with open('outputfile-test-{}.json'.format(i), 'w') as ofh:
json.dump(entry, ofh)
You can further filter the entries as needed, or use data from the entries to generate a filename; entry['name'] is the name value of each entry, for example.
What do to with json ? Well, the same thing as with XML : parse it.
=> http://docs.python.org/2/library/json.html
You need a tree-search algorithm for this:
def locateByName(e,name):
if e.get('name',None) == name:
return e
for child in e.get('children',[]):
result = locateByName(child,name)
if result is not None:
return result
return None
Now you can use this recursive function to locate the element you want:
node = locateByName(output_json, 'BoxDet')
print node['name'],node['Ids']
when you try to use a for loop on a dict, without any special consideration, you get only the keys out of the dict. That is:
>>> my_dict = {'foo': 'bar', 'baz':'quux'}
>>> list(my_dict)
['foo', 'baz']
>>> for x in my_dict:
... print repr(x)
'foo'
'baz'
The most usual thing to do is to use dict.iteritems() (just dict.items() in python 3)
>>> for x in my_dict.iteritems():
... print repr(x)
('foo', 'bar')
('baz', 'quux')
Or you can fetch the value for the key yourself:
>>> for x in my_dict:
... print repr(x), repr(my_dict[x])
'foo' 'bar'
'baz' 'quux'
If you want the list of nodes used to reach the bottom id you could use the following:
def get_parent(json_tree, target_id):
for element in json_tree:
if element['id'] == target_id:
return [element['id']]
else:
if element['child']:
check_child = get_parent(element['child'], target_id)
if check_child:
return [element['id']] + check_child
This creates a list when the id is matched, and then as it is passed back up the loops, adds the id for each level to the front of the list.
So, correcting your json to be proper (no trailing commas) and calling the function:
js = json.loads('[{"id": 1,"child": [{"id": 4,"child": []},{"id": 2,"child": [{"id": 37,"child": []},{"id": 39,"child": []}]},{"id": 3,"child": []}]},{"id": 120,"child": []},{"id": 121,"child": [{"id": 122,"child": []}]}]')
print(get_parent(js, 37))
prints
[1, 2, 37]
code.py:
import sys
TREE = [
{
"id": 1,
"child": [
{
"id": 4,
"child": [],
},
{
"id": 2,
"child": [
{
"id": 37,
"child": [],
},
{
"id": 39,
"child": [],
}
]
},
{
"id": 3,
"child": [],
},
]
},
{
"id": 120,
"child": [],
},
{
"id": 121,
"child": [
{
"id": 122,
"child": [],
}
]
}
]
def get_chain_ids(tree_dict, target_id, depth=0):
cur_id = tree_dict["id"]
if cur_id == target_id:
yield cur_id
else:
yield_cur_id = False
for child_dict in tree_dict["child"]:
for child_id in get_chain_ids(child_dict, target_id, depth=depth + 1):
yield_cur_id = True
yield child_id
if yield_cur_id:
yield cur_id
if __name__ == "__main__":
print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
for item in TREE:
print("\nSearching tree (id: {:d})...".format(item["id"]))
ids = get_chain_ids(item, 37)
if (ids):
for item in ids:
print(item)
Notes:
- Uses [Python]: Generators
- The json (
TEXTdict) was incorrect, I had to adjust it (besides formatting) get_chain_idstakes the tree root (tree_dict) which is a dictionary, andtarget_idas arguments, and returns a generator yielding all the node ids fromtarget_idto the root iddepthis currently not used- Since
TREEis alistof nodes, I had to iterate over it and pass each element to the function - It doesn't handle cases where a node is malformed (lacks
"id"or"child"keys, or if their values are not as expected)
Output:
(py35x64_test) E:\Work\Dev\StackOverflow\q048865303>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32 Searching tree (id: 1)... 37 2 1 Searching tree (id: 120)... Searching tree (id: 121)...
You must convert json to dict and then the labels are the same as the keys.
import json
a = json.dumps({"Name": "Robert",
"Date" : "January 17th, 2017",
"Address" : "Jakarta"})
for key in json.loads(a):
print(key)
output:
Name
Date
Address
Optional:
If you want to access the values of each item
import json
a = json.dumps({"Name": "Robert",
"Date" : "January 17th, 2017",
"Address" : "Jakarta"})
d = json.loads(a)
for key in d:
print("key: {}, value: {}".format(key, d[key]))
Python2
for key, value in json.loads(a).iteritems():
print("key: {}, value: {}".format(key, value))
Python3
for key, value in json.loads(a).items():
print("key: {}, value: {}".format(key, value))
Output:
key: Name, value: Robert
key: Date, value: January 17th, 2017
key: Address, value: Jakarta
Assumptions made:
- I assumed that you are using python3.x
You can do it as follows:
import json
a = json.dumps({"Name": "Robert", "Date" : "January 17th, 2017", "Address" : "Jakarta"})
a_dict = json.loads(a)
for key in a_dict.keys():
print (key)