python json数据的读写

在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_hookobject_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

展开阅读全文