Python JSON
JSON
JSON - JavaScript Object Notation
- json
JSON is basically the data format used by JavaScript. Because its universal availability it became the de-facto standard for data communication between many different languages. Most dynamic languages have an fairly good mapping between JSON and their own data structures. Lists and dictionaries in the case of Python.
Documentation of the Python json library.
Examples:
{"fname": "Foo", "lname": "Bar", "email": null, "children": ["Moo", "Koo", "Roo"], "fixed": ["a", "b"]}
JSON dumps
-
dumps
-
Dictionaries and lists are handles
-
Tuples are indistinguishable from lists
-
Always Double-quotes
-
nullinstead ofNone -
No trailing comma
import json
data = {
"fname" : 'Foo',
"lname" : 'Bar',
"email" : None,
"children" : [
"Moo",
"Koo",
"Roo",
],
"fixed": ("a", "b"),
}
print(data)
json_str = json.dumps(data)
print(json_str)
with open('data.json', 'w') as fh:
fh.write(json_str)
{'fname': 'Foo', 'lname': 'Bar', 'email': None, 'children': ['Moo', 'Koo', 'Roo'], 'fixed': ('a', 'b')}
{"fname": "Foo", "lname": "Bar", "email": null, "children": ["Moo", "Koo", "Roo"], "fixed": ["a", "b"]}
dumps can be used to take a Python data structure and generate a string in JSON format. That string can then be saved in a file,
inserted in a database, or sent over the wire.
JSON loads
- loads
import json
with open('data.json') as fh:
json_str = fh.read()
print(json_str)
data = json.loads(json_str)
print(data)
{"fname": "Foo", "lname": "Bar", "email": null, "children": ["Moo", "Koo", "Roo"], "fixed": ["a", "b"]}
{'fname': 'Foo', 'lname': 'Bar', 'email': None, 'children': ['Moo', 'Koo', 'Roo'], 'fixed': ['a', 'b']}
dump
- dump
import json
data = {
"fname" : 'Foo',
"lname" : 'Bar',
"email" : None,
"children" : [
"Moo",
"Koo",
"Roo",
],
}
print(data)
with open('data.json', 'w') as fh:
json.dump(data, fh)
As a special case dump will save the string in a file or in other stream.
load
- load
import json
with open('data.json', 'r') as fh:
data = json.load(fh)
print(data)
Round trip
- loads
- dumps
import json
import os
import time
import sys
if len(sys.argv) != 2:
exit("Usage: {sys.argv[0]} NAME")
data = {
'name': [],
'time': [],
}
filename = 'mydata.json'
if os.path.exists(filename):
with open(filename) as fh:
json_str = fh.read()
# print(json_str)
data = json.loads(json_str)
data['name'].append(sys.argv[1])
data['time'].append(time.time())
with open(filename, 'w') as fh:
json_str = json.dumps(data, indent=4)
fh.write(json_str)
Pretty print JSON
import json
data = {
"name" : "Foo Bar",
"grades" : [23, 47, 99, 11],
"children" : {
"Peti Bar" : {
"email": "peti@bar.com",
},
"Jenny Bar" : {
"phone": "12345",
},
}
}
print(data)
print(json.dumps(data))
print(json.dumps(data, indent=4, separators=(',', ': ')))
{'name': 'Foo Bar', 'grades': [23, 47, 99, 11], 'children': {'Peti Bar': {'email': 'peti@bar.com'}, 'Jenny Bar': {'phone': '12345'}}}
{"name": "Foo Bar", "grades": [23, 47, 99, 11], "children": {"Peti Bar": {"email": "peti@bar.com"}, "Jenny Bar": {"phone": "12345"}}}
{
"name": "Foo Bar",
"grades": [
23,
47,
99,
11
],
"children": {
"Peti Bar": {
"email": "peti@bar.com"
},
"Jenny Bar": {
"phone": "12345"
}
}
}
Serialize Datetime objects in JSON
Sort keys in JSON
import json
data = {
"name" : "Foo Bar",
"grades" : [23, 47, 99, 11],
"children" : {
"Peti Bar" : {
"email": "peti@bar.com",
},
"Jenny Bar" : {
"phone": "12345",
},
}
}
print(json.dumps(data, sort_keys=True, indent=4, separators=(',', ': ')))
{
"children": {
"Jenny Bar": {
"phone": "12345"
},
"Peti Bar": {
"email": "peti@bar.com"
}
},
"grades": [
23,
47,
99,
11
],
"name": "Foo Bar"
}
Set order of keys in JSON - OrderedDict
- collections
- OrderedDict
from collections import OrderedDict
import json
d = {}
d['a'] = 1
d['b'] = 2
d['c'] = 3
d['d'] = 4
planned_order = ('b', 'c', 'd', 'a')
e = OrderedDict(sorted(d.items(), key=lambda x: planned_order.index(x[0])))
print(e)
out = json.dumps(e, sort_keys=False, indent=4, separators=(',', ': '))
print(out)
print('-----')
# Create index to value mapping dictionary from a list of values
planned_order = ('b', 'c', 'd', 'a')
plan = dict(zip(planned_order, range(len(planned_order))))
print(plan)
f = OrderedDict(sorted(d.items(), key=lambda x: plan[x[0]]))
print(f)
out = json.dumps(f, sort_keys=False, indent=4, separators=(',', ': '))
print(out)
OrderedDict([('b', 2), ('c', 3), ('d', 4), ('a', 1)])
{
"b": 2,
"c": 3,
"d": 4,
"a": 1
}
-----
{'b': 0, 'c': 1, 'd': 2, 'a': 3}
OrderedDict([('b', 2), ('c', 3), ('d', 4), ('a', 1)])
{
"b": 2,
"c": 3,
"d": 4,
"a": 1
}
Exercise: Counter in JSON
Write a script that will provide several counters. The user can provide an argument on the command line and the script will increment and display that counter. Keep the current values of the counters in a single JSON file. The script should behave like this:
$ python counter.py foo
1
$ python counter.py foo
2
$ python counter.py bar
1
$ python counter.py foo
3
- Extend the exercise so if the user provides the
--listflag then all the indexes are listed (and no counting is done). - Extend the exercise so if the user provides the
--delete fooparameter then the counterfoois removed.
Exercise: Phone book in JSON
Write a script that acts as a phonebook. As "database" use a file in JSON format.
$ python phone.py Foo 123
Foo added
$ python phone.py Bar
Bar is not in the phonebook
$ python phone.py Bar 456
Bar added
$ python phone.py Bar
456
$ python phone.py Foo
123
- If the user provides
Bar 123save 123 for Bar. - If the user provides
Bar 456tell the user Bar already has a phone number. - To update a phone-number the user must provide
--update Bar 456 - To remove a name the user must provide
--delete Bar - To list all the names the user can provide
--list
Solution: Counter in JSON
import json
import sys
import os
filename = 'counter.json'
if len(sys.argv) != 2:
print("Usage: " + sys.argv[0] + " COUNTER")
exit()
counter = {}
if os.path.exists(filename):
with open(filename) as fh:
json_str = fh.read()
counter = json.loads(json_str)
name = sys.argv[1]
if name in counter:
counter[name] += 1
else:
counter[name] = 1
print(counter[name])
with open(filename, 'w') as fh:
json_str = json.dumps(counter)
fh.write(json_str)
Solution: Phone book
import sys
import json
import os
def main():
filename = 'phonebook.json'
phonebook = {}
if os.path.exists(filename):
with open(filename) as fh:
json_str = fh.read()
phonebook = json.loads(json_str)
if len(sys.argv) == 2:
name = sys.argv[1]
if name in phonebook:
print(phonebook[name])
else:
print("{} is not in the phonebook".format(name))
return
if len(sys.argv) == 3:
name = sys.argv[1]
phone = sys.argv[2]
phonebook[name] = phone
with open(filename, 'w') as fh:
json_str = json.dumps(phonebook)
fh.write(json_str)
return
print("Invalid number of parameters")
print("Usage: {} username [phone]".format(sys.argv[0]))
if __name__ == '__main__':
main()