之前学习了序列化的一种方法——pickle序列化。
其核心是通过pickle.dumps()将对象序列化为str,之后再将这个str写入文件。打开刚才的文件,我们发现,刚才辛苦序列化半天的东西,竟然完全是一些莫名字符的堆积——Python保存的对象内部信息。因此当需要将对象从磁盘读取到内存时,首先要把内容读成str,再通过pickle.loads()反序列化出对象。
但是Pickle的问题和所有其他编程语言特有的序列化问题一样,它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据。
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。所以也就引出了json这个强大的序列化方法。
- 实现将一个python类型转换为json对象:
import json
# python字典类型转换为json对象
d = dict(name='zhuzhuzhu', age='20', score='99')
x = json.dumps(d)
print x
OUTPUT : {“age”: “20”, “score”: “99”, “name”: “zhuzhuzhu”}
- 实现将json对象再转换为python类型
y = json.loads(x)
print y
OUTPUT : {u’age’: u’20’, u’score’: u’99’, u’name’: u’zhuzhuzhu’}
注意
反序列化得到的所有字符串对象默认都是unicode而不是str。由于JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的str或unicode与JSON的字符串之间转换。
- 如果需要处理的不是字符串而是文件,可以使用json.dump()和json.load()进行编码和解码json数据。
# 写入 JSON 数据
with open('data.json', 'w') as f:
json.dump(data, f)
# 读取数据
with open('data.json', 'r') as f:
data = json.load(f)
- json可以对一个字典表示的对象进行序列化,但是很多时候,我们更倾向于用class——类来表示对象。
class Animal(object):
def __init__(self, species, color, weight):
self.species = species
self.color = color
self.weight = weight
dog = Animal('Dog', 'red', '50')
print json.dumps(dog)
运行之后发现报错,错误原因是Animal对象不是一个可序列化为JSON的对象。
通过查资料可得,dumps()的可选参数default可以把任意一个对象变成一个可序列为JSON的对象。
因此,我们专门为类Animal写一个转换函数,将其作为参数default的值传进去。
class Animal(object):
def __init__(self, species, color, weight):
self.species = species
self.color = color
self.weight = weight
def animal2dic(animal):
return{
'species': animal.species,
'color': animal.color,
'weight': animal.weight
}
dog = Animal('Dog', 'red', '50')
print json.dumps(dog, default=animal2dic)
OUTPUT : {“color”: “red”, “species”: “Dog”, “weight”: “50”}
另外,可以将任意的class的实例变为dict,因为通常class的实例都有一个dict属性,它就是一个dict,用来存储实例变量。也有少数例外,比如定义了slots的class。
print json.dumps(s, default=lambda obj: obj.__dict__)
同样,我们要将一个json对象反序列化为类的对象实例,首先用loads()方法转换出一个dict对象,然后,定义一个将dict转换为类的函数,将其作为object_hook参数的值传入。
def dict2animal(dic):
return Animal(dic['species'], dic['color'], dic['weight'])
json_str = '{"species": "Dog", "color": "red", "weight": 50}'
print json.loads(json_str, object_hook=dict2animal)
OUTPUT : <main.Animal object at 0x000000000555E8D0>
打印出来的是反序列化的Animal实例对象。