I have a dict like this:
sample = {'ObjectInterpolator': 1629, 'PointInterpolator': 1675, 'RectangleInterpolator': 2042}
I can't figure out how to dump the dict to a JSON file as showed below:
{
"name": "interpolator",
"children": [
{"name": "ObjectInterpolator", "size": 1629},
{"name": "PointInterpolator", "size": 1675},
{"name": "RectangleInterpolator", "size": 2042}
]
}
Is there a pythonic way to do this?
You may guess that I want to generate a d3 treemap.
import json
with open('result.json', 'w') as fp:
json.dump(sample, fp)
This is an easier way to do it.
In the second line of code the file result.json gets created and opened as the variable fp.
In the third line your dict sample gets written into the result.json!
Combine the answer of #mgilson and #gnibbler, I found what I need was this:
d = {
"name": "interpolator",
"children": [{
'name': key,
"size": value
} for key, value in sample.items()]
}
j = json.dumps(d, indent=4)
with open('sample.json', 'w') as f:
print >> f, j
It this way, I got a pretty-print json file.
The tricks print >> f, j is found from here:
http://www.anthonydebarros.com/2012/03/11/generate-json-from-sql-using-python/
d = {"name":"interpolator",
"children":[{'name':key,"size":value} for key,value in sample.items()]}
json_string = json.dumps(d)
Since python 3.7 the ordering of dicts is retained https://docs.python.org/3.8/library/stdtypes.html#mapping-types-dict
Dictionaries preserve insertion order. Note that updating a key does not affect the order. Keys added after deletion are inserted at the end
Also wanted to add this (Python 3.7)
import json
with open("dict_to_json_textfile.txt", 'w') as fout:
json_dumps_str = json.dumps(a_dictionary, indent=4)
print(json_dumps_str, file=fout)
Update (11-04-2021): So the reason I added this example is because sometimes you can use the print() function to write to files, and this also shows how to use the indentation (unindented stuff is evil!!). However I have recently started learning about threading and some of my research has shown that the print() statement is not always thread-safe. So if you need threading you might want to be careful with this one.
This should give you a start
>>> import json
>>> print json.dumps([{'name': k, 'size': v} for k,v in sample.items()], indent=4)
[
{
"name": "PointInterpolator",
"size": 1675
},
{
"name": "ObjectInterpolator",
"size": 1629
},
{
"name": "RectangleInterpolator",
"size": 2042
}
]
with pretty-print format:
import json
with open(path_to_file, 'w') as file:
json_string = json.dumps(sample, default=lambda o: o.__dict__, sort_keys=True, indent=2)
file.write(json_string)
If you're using Path:
example_path = Path('/tmp/test.json')
example_dict = {'x': 24, 'y': 25}
json_str = json.dumps(example_dict, indent=4) + '\n'
example_path.write_text(json_str, encoding='utf-8')
Related
I am trying to delete an element in a json file,
here is my json file:
before:
{
"names": [
{
"PrevStreak": false,
"Streak": 0,
"name": "Brody B#3719",
"points": 0
},
{
"PrevStreak": false,
"Streak": 0,
"name": "XY_MAGIC#1111",
"points": 0
}
]
}
after running script:
{
"names": [
{
"PrevStreak": false,
"Streak": 0,
"name": "Brody B#3719",
"points": 0
}
]
}
how would I do this in python? the file is stored locally and I am deciding which element to delete by the name in each element
Thanks
I would load the file, remove the item, and then save it again. Example:
import json
with open("filename.json") as f:
data = json.load(f)
f.pop(data["names"][1]) # or iterate through entries to find matching name
with open("filename.json", "w") as f:
json.dump(data, f)
You will have to read the file, convert it to python native data type (e.g. dictionary), then delete the element and save the file. In your case something like this could work:
import json
filepath = 'data.json'
with open(filepath, 'r') as fp:
data = json.load(fp)
del data['names'][1]
with open(filepath, 'w') as fp:
json.dump(data, fp)
Try this:
# importing the module
import ast
# reading the data from the file
with open('dictionary.txt') as f:
data = f.read()
print("Data type before reconstruction : ", type(data))
# reconstructing the data as a dictionary
a_dict = ast.literal_eval(data)
{"names":[a for a in a_dict["names"] if a.get("name") !="XY_MAGIC#1111"]}
import json
with open("test.json",'r') as f:
data = json.loads(f.read())
names=data.get('names')
for idx,name in enumerate(names):
if name['name']=='XY_MAGIC#1111':
del names[idx]
break
print(names)
In order to read the file best approach would be using the with statement after which you could just use pythons json library and convert json string to python dict. once you get dict you can access the values and do your operations as required. you could convert it as json using json.dumps() then save it
This does the right thing useing the python json module, and prettyprints the json back to the file afterwards:
import json
jsonpath = '/path/to/json/file.json'
with open(jsonpath) as file:
j = json.loads(file.read())
names_to_remove = ['XY_MAGIC#1111']
for element in j['names']:
if element['name'] in names_to_remove:
j['names'].remove(element)
with open(jsonpath, 'w') as file:
file.write(json.dumps(j, indent=4))
I have a json file, and I'm reading this file with json library
This is the json content (example)
{
"type": "champion",
"format": "standAloneComplex",
"version": "10.18.1",
"data": {
"Aatrox": {
"version": "10.18.1",
"id": "Aatrox",
"key": "266",
"name": "Aatrox"
},
"Ahri": {
"version": "10.18.1",
"id": "Ahri",
"key": "103",
"name": "Ahri",
},
}
Now how can I check if key is equal to 266 and return the value of name?
I was trying with something like this
import json
with open('./source/champion.json') as json_file:
data_champs = json.load(json_file)['data']
for champ in data_champs:
for champ_info in data_champs[champ]:
if champ['key'] == 266:
print(champ)
But return TypeError: string indices must be integers
Try the following:
import json
with open('./source/champion.json') as json_file:
for name, info in json.load(json_file)['data'].items():
if info['key'] == 266:
print(name)
Or even better, we can close the file after we get the data and not keep it open during processing:
import json
with open('./source/champion.json') as json_file:
data = json.load(json_file)['data']
for name, info in data.items():
if info['key'] == 266:
print(name)
Explanation
The easiest way to iterate over a dict's elements is by using its .items() method:
for key, value in d.items():
print(key, "-->", value)
below (iterating over the values only since the keys are not important here)
import json
with open('data.json') as f:
data = json.load(f)['data']
for v in data.values():
if v['key'] == '266':
print(v['name'])
break
output
Aatrox
Here you go:
import json
with open('champion.json') as json_file:
data_champs = json.load(json_file)['data']
for data in data_champs.keys():
if data_champs[data]['key']=='266':
print(data_champs[data]['name'])
Prints:
Aatrox
I am currently reading in a JSON file, adding a key and writing it back out to the same file using this procedure
with open('data.json', 'r+') as f:
data = json.load(f)
temp_key={"test":"val"}
data["test"]["new_key"] = temp_key
f.seek(0) # <--- should reset file position to the beginning.
json.dump(data, f, indent=2)
f.truncate() # remove remaining part
(adopted from here)
but the issue is that it does not maintain order. for instance if I read in:
{
"test": {
"something": "something_else"
},
"abc": {
"what": "huh"
}
}
the output turns out as:
{
"abc": {
"what": "huh"
},
"test": {
"something": "something_else",
"new_key": {
"test": "val"
}
}
}
When I would like it to be:
{
"test": {
"something": "something_else",
"new_key": {
"test": "val"
}
},
"abc": {
"what": "huh"
}
}
I realise that JSON is a key/value based structure and the order does not matter, but is there a way of making the modification and maintaining the original structure?
As I said in a comment, you can use a collections.OrderedDict along with the optional object_pairs_hook keyword argument accepted by json.load() (in Python 2.7) to preserve the order of the original data when you rewrite the file.
This is what I meant:
#!/usr/bin/env python2
from collections import OrderedDict
import json
with open('ordered_data.json', 'r+') as f:
data = json.load(f, object_pairs_hook=OrderedDict)
temp_key = {"test": "val"}
data["test"]["new_key"] = temp_key
f.seek(0) # Reset file position to the beginning.
json.dump(data, f, indent=2)
f.truncate() # Remove remaining part.
I need to remove data from a json, at the minute i am using the following code:
import json
with open('E:/file/timings.json', 'r+') as f:
qe = json.load(f)
for item in qe['times']:
if item['Proc'] == 'APS':
print(f'{item["Num"]}')
del item
json.dump(qe, f, indent=4, sort_keys=False, ensure_ascii=False)
This doesn't delete anything from the JSON, here is a small example of my JSON file
{
"times": [
{
"Num": "12345678901234567",
"Start_Time": "2016-12-14 15:54:35",
"Proc": "UPD",
},
{
"Num": "12345678901234567",
"Start_Time": "2016-12-08 15:34:05",
"Proc": "APS",
},
{
"Num": "12345678901234567",
"Start_Time": "2016-11-30 11:20:21",
"Proc": "Dev,
i would like it to look like this:
{
"times": [
{
"Num": "12345678901234567",
"Start_Time": "2016-12-14 15:54:35",
"Proc": "UPD",
},
{
"Num": "12345678901234567",
"Start_Time": "2016-11-30 11:20:21",
"Proc": "Dev,
as you can see the portion containing APS as the process has been removed
You could save your initial json and then create new one that doesn't contain items which 'Proc' is equal to 'APS' (here new_json) and then overwrite your json file with that new_json.
import json
content = json.loads(open('timings.json', 'r').read())
new_json = {'times': []}
for item in content['times']:
if item['Proc'] != 'APS':
new_json['times'].append(item)
file = open('timings.json', 'w')
file.write(json.dumps(new_json, indent=4, sort_keys=False, ensure_ascii=False))
file.close()
It is not a good practice to delete element while iterating the list.
Use:
import json
with open('E:/file/timings.json', 'r') as f:
qe = json.load(f)
qe = [item for item in qe['times'] if item['Proc'] != 'APS'] #Delete Required element.
with open('E:/file/timings.json', 'w') as f:
json.dump(qe, f, indent=4, sort_keys=False, ensure_ascii=False)
del as you're using it, removes the variable item from your session, but leaves the actual item untouched in the data structure. You need to explicitly remove whatever item is pointing to from your data structure. Also, you want to avoid deleting items from a list while you are iterating over said list. You should recreate your entire list:
qe['times'] = [item for item in qe['times'] if item['Proc'] != 'APS']
You can use a method if you need to print:
def keep_item(thing):
if item['Proc'] == 'APS':
print thing['Num']
return False
else:
return True
qe['times'] = [item for item in qe['times'] if keep_item(item)]
You can use the below method to remove the element from list:
for i,item in enumerate(qe['times']):
if item['Proc'] == 'APS':
qe['times'].pop(i)
and then write back to the JSON file.
I'm trying to add key value pairs into the existing JSON file. I am able to concatenate to the parent label, How to add value to the child items?
JSON file:
{
"students": [
{
"name": "Hendrick"
},
{
"name": "Mikey"
}
]
}
Code:
import json
with open("input.json") as json_file:
json_decoded = json.load(json_file)
json_decoded['country'] = 'UK'
with open("output.json", 'w') as json_file:
for d in json_decoded[students]:
json.dump(json_decoded, json_file)
Expected Results:
{
"students": [
{
"name": "Hendrick",
"country": "UK"
},
{
"name": "Mikey",
"country": "UK"
}
]
}
You can do the following in order to manipulate the dict the way you want:
for s in json_decoded['students']:
s['country'] = 'UK'
json_decoded['students'] is a list of dictionaries that you can simply iterate and update in a loop. Now you can dump the entire object:
with open("output.json", 'w') as json_file:
json.dump(json_decoded, json_file)
import json
with open("input.json", 'r') as json_file:
json_decoded = json.load(json_file)
for element in json_decoded['students']:
element['country'] = 'UK'
with open("output.json", 'w') as json_out_file:
json.dump(json_decoded, json_out_file)
opened a json file i.e. input.json
iterated through each of its element
add a key named "country" and dynamic value "UK", to each element
opened a new json file with the modified JSON.
Edit:
Moved writing to output file inside to first with segment. Issue with earlier implemenation is that json_decoded will not be instantiated if opening of input.json fails. And hence, writing to output will raise an exception - NameError: name 'json_decoded' is not defined
This gives [None, None] but update the dict:
a = {'students': [{'name': 'Hendrick'}, {'name': 'Mikey'}]}
[i.update({'country':'UK'}) for i in a['students']]
print(a)