在python中使用 json 模块可以轻易处理json格式数据。json.dumps() 和 json.loads() 方法将python对象和json数据进行互换。
>>> import json
>>> data = {
'name' : 'ACME',
'shares' : 100,
'price' : 542.23
}
>>> json_str = json.dumps(data)
>>> json_str
'{"name": "ACME", "shares": 100, "price": 542.23}'
>>> d = json.loads(json_str)
>>> d
{'name': 'ACME', 'shares': 100, 'price': 542.23}
>>> d['name']
'ACME'
可以使用文件代替字符串,此时使用 json.dump() 和 json.load() 方法
>>> with open(r'e:\path\data.json', 'w') as f:
json.dump(data, f)
>>> with open(r'e:\path\data.json') as f:
d = json.load(f)
>>> d
{'name': 'ACME', 'shares': 100, 'price': 542.23}
json 模块可以处理python的基本类型,但注意一些小的变化:False to 'false'; True to 'true'; None to 'null'... 同时,在字典中key会被处理成字符串形式
>>> json.dumps(False)
'false'
>>> json.dumps(True)
'true'
>>> dic = {'a': True, 'b': 'Hello', 'c':None, 4: 4.0}
>>> json.dumps(dic)
'{"a": true, "b": "Hello", "c": null, "4": 4.0}'
对于大的json数据,深层次第结构或者大量的字段对应显示都是不友好的,引用 pprint 美化json数据格式
>>> from pprint import pprint
>>> d
{'name': 'ACME', 'shares': 100, 'price': 542.23}
>>> pprint(d)
{'name': 'ACME', 'price': 542.23, 'shares': 100}
>>> d.update([('abc', 123),('bcd', 456),('efg', 677)])
>>> pprint(d)
{'abc': 123,
'bcd': 456,
'efg': 677,
'name': 'ACME',
'price': 542.23,
'shares': 100}
>>> pprint(d, indent=4) # 缩进 4 空格
{ 'abc': 123,
'bcd': 456,
'efg': 677,
'name': 'ACME',
'price': 542.23,
'shares': 100}
json 解码 data 数据会创建一个 dict,如果想要不同的类型,可以指定 object_pairs_hook 或 object_hook,此时会创建指定的类型。如果 object_pairs_hook 和 object_hook 同时指定,object_pairs_hook 优先
>>> data
{'name': 'ACME', 'shares': 100, 'price': 542.23}
>>> d = json.dumps(data, sort_keys=True) # key 排序
>>> d
'{"name": "ACME", "price": 542.23, "shares": 100}'
>>> from collections import OrderedDict
>>> json.loads(d, object_pairs_hook=OrderedDict) # 返回不再是 dict
OrderedDict([('name', 'ACME'), ('price', 542.23), ('shares', 100)])
>>>
>>> class JSONObject:
def __init__(self, d):
self.__dict__ = d
>>> obj = json.loads(d, object_hook=JSONObject) # 创建 JSONObject
>>> obj
<__main__.JSONObject object at 0x0000000003019198>
>>> obj.name
'ACME'
>>> obj.shares, obj.price
(100, 542.23)
>>>
>>> obj = json.loads(d, object_hook=JSONObject, object_pairs_hook=OrderedDict) # object_pairs_hook 优先
>>> obj
OrderedDict([('name', 'ACME'), ('price', 542.23), ('shares', 100)])
>>> obj['name'], obj['price']
('ACME', 542.23)
自定义的类与json数据互转
使用 default 将自定义的类转成json数据
>>> class User:
def __init__(self, name, age):
self.name = name
self.age = age
>>> user = User('a', 1)
>>> json.dumps(user)
Traceback (most recent call last):
File "<pyshell#71>", line 1, in <module>
json.dumps(user)
File "D:\work\Python\Python36\lib\json\__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
File "D:\work\Python\Python36\lib\json\encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "D:\work\Python\Python36\lib\json\encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "D:\work\Python\Python36\lib\json\encoder.py", line 180, in default
o.__class__.__name__)
TypeError: Object of type 'User' is not JSON serializable
>>>
>>> def serialize_instance(obj):
dic = {'__classname__': type(obj).__name__}
dic.update(vars(obj))
return dic
>>> obj_json = json.dumps(user, default=serialize_instance)
>>> obj_json
'{"__classname__": "User", "name": "a", "age": 1}'
使用 object_hook 将 obj_json 还原成自定义的类
>>> classes = {'User': User}
>>> obj_json
'{"__classname__": "User", "name": "a", "age": 1}'
>>> def unserialize_object(dic):
clsname = dic.pop('__classname__', None)
if clsname:
cls = classes[clsname]
obj = cls.__new__(cls)
for key, value in dic.items():
setattr(obj, key, value)
return obj
else:
return dic
>>> o = json.loads(obj_json, object_hook=unserialize_object)
>>> o
<__main__.User object at 0x0000000003019C50>
>>> o.name
'a'
>>> o.age
1