序列化与反序列化的应用

  在python中,我们需要将内置的数据结构如元组、列表、字典处理为str类型,这个时候就需要进行序列化处理;如果进行反序列化处理,数据类型则仍然是列表、字典,但是元组经过反序列化后,数据类型会转为列表。进行序列化和反序列化,我们需要用到json库。在这个库中,序列化和反序列化处理分为两部分,一部分是直接对数据类型进行处理,另一部分是对文件内容的处理。

1.1 数据类型的直接处理

  对数据类型直接进行序列化和反序列化,我们需要用到json库中的dumps和loads方法,下面我们来看几个实例

1.1.1 对元组的序列化与反序列化处理

 1 import json
 2 
 3 
 4 tuple1 = (1, 2, 3)
 5 print('未处理之前的数据类型:', type(tuple1))
 6 
 7 #对元组进行序列化处理
 8 tuple1_str = json.dumps(tuple1)
 9 print('经过序列化处理之后的数据类型:', type(tuple1_str), tuple1_str)
10 
11 #对字符串tuple1_str进行反序列化处理
12 str_tuple1 = json.loads(tuple1_str)
13 print('经过反序列化处理之后的数据类型:', type(str_tuple1), str_tuple1)

运行后得到结果:

未处理之前的数据类型: <class 'tuple'>
经过序列化处理之后的数据类型: <class 'str'> [1, 2, 3]
经过反序列化处理之后的数据类型: <class 'list'> [1, 2, 3]

  从输出结果中,我们可以看到元组在经过序列化处理后,数据类型变成了str类型,在经过反序列化之后,数据类型并没有变回元组,而是列表。

1.1.2 对列表的序列化与反序列化处理

 1 list1 = [1, 2, 3]
 2 print('未处理之前的数据类型:', type(list1))
 3 
 4 #对列表进行序列化处理
 5 list1_str = json.dumps(list1)
 6 print('经过序列化处理之后的数据类型:', type(list1_str), list1_str)
 7 
 8 #对字符串list1_str进行反序列化处理
 9 str_list1 = json.loads(list1_str)
10 print('经过反序列化处理之后的数据类型:', type(str_list1), str_list1)

运行后得到结果:

未处理之前的数据类型: <class 'list'>
经过序列化处理之后的数据类型: <class 'str'> [1, 2, 3]
经过反序列化处理之后的数据类型: <class 'list'> [1, 2, 3]

  我们可以看到,列表在经过序列化处理后,数据类型变成了str 类型;经过反序列化之后,数据类型又变回了list。

1.1.3 对字典的序列化和反序列化处理

 1 dict1 = {'id': 1, 'name': '张三'}
 2 print('未处理之前的数据类型:', type(dict1))
 3 
 4 #对字典进行序列化处理
 5 dict1_str = json.dumps(dict1)
 6 print('经过序列化处理之后的数据类型:', type(dict1_str), dict1_str)
 7 
 8 #对字符串dict1_str进行反序列化处理
 9 str_dict1 = json.loads(dict1_str)
10 print('经过反序列化处理之后的数据类型:', type(str_dict1), str_dict1)

运行后得到结果:

未处理之前的数据类型: <class 'dict'>
经过序列化处理之后的数据类型: <class 'str'> {"id": 1, "name": "\u5f20\u4e09"}
经过反序列化处理之后的数据类型: <class 'dict'> {'id': 1, 'name': '张三'}

  字典在经过序列化后也是变成了str的数据类型,反序列化后又重新变回了字典的数据类型

1.2 文件的序列化和反序列化

1.2.1 文件的序列化

  在介绍文件的序列化与反序列化之前,先来看一个例子:

1 import os
2 
3 
4 data_dir = os.path.join(os.path.dirname(__file__), 'data', 'api.json')
5 
6 dict1 = {'name': '张三'}
7 with open(data_dir, 'w') as fp:
8    fp.write(dict1)

运行后得到结果:

Traceback (most recent call last):
  File "/Users/yezhenxiang/PycharmProjects/Test/lagou.py", line 13, in <module>
    fp.write(dict1)
TypeError: write() argument must be str, not dict

  上面的例子想要实现的目的是将dict1写入到文件api.json中,但是我们按照正常的方式写入时,最终报错了,这是因为dict1的数据类型时字典,程序无法直接将字典写入。这个时候,就要使用到文件的序列化了

  先来看下dump方法的源码:

1 def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
2         allow_nan=True, cls=None, indent=None, separators=None,
3         default=None, sort_keys=False, **kw):

  从上面的源码中,需要关注的是dump方法中第一个和第二个参数,分别是文件的对象和打开的文件句柄,了解了dump的原理后,就可以使用dump来进行序列化写入文件了,来看下面的例子:

1 import json
2 import os
3 
4 
5 data_dir = os.path.join(os.path.dirname(__file__), 'data', 'api.json')
6 
7 dict1 = {'name': '张三'}
8 json.dump(dict1, open(data_dir, 'w'))

运行程序后,dict1成功写入api.json文件中

{"name": "\u5f20\u4e09"}

  文件的序列化我们使用dump,这样就可以将不是string类型的数据类型写入到文件中了。但是在输出的结果中,写入到文件是bytes类型,如果我们想要将自己看的懂的文件写入,可以使用ensure_ascii=False,如下:

1 json.dump(dict1, open(data_dir, 'w', encoding='utf-8'), ensure_ascii=False)

1.2.2 文件的反序列化

  那么什么时候需要对文件进行反序列化呢。先来读取一下上面保存的文件内容看一下:

 1 import json
 2 import os
 3 
 4 
 5 
 6 data_dir = os.path.join(os.path.dirname(__file__), 'data', 'api.json')
 7 
 8 dict1 = {'name': '张三'}
 9 #对文件进行序列化写入
10 json.dump(dict1, open(data_dir, 'w', encoding='utf-8'), ensure_ascii=False)
11 
12 #对保存的文件进行读取
13 file_dict = open(data_dir)
14 content = file_dict.read()
15 print(type(content), content)

运行后得到结果:

<class 'str'> {"name": "张三"}

  可以从读读取的内容中看出,文件中保存的数据是str类型的,这样显然不利于我们对文件内容的处理,所以如果在需要处理文件内容的时候,我们就需要根据情况进行反序列化将文件中的内容读取出来

  反序列化的方法如下:

 1 import json
 2 import os
 3 
 4 
 5 
 6 data_dir = os.path.join(os.path.dirname(__file__), 'data', 'api.json')
 7 
 8 dict1 = {'name': '张三'}
 9 json.dump(dict1, open(data_dir, 'w', encoding='utf-8'), ensure_ascii=False)
10 
11 #对文件进行反序列化
12 dict1 = json.load(open(data_dir, 'r'))
13 print(dict1, type(dict1))

运行后得到结果:

{'name': '张三'} <class 'dict'>

  在最后的打印中可以看到文件的类型是字典类型,我们就可以用处理字典的方式来有效的操作文件中的内容了。

猜你喜欢

转载自www.cnblogs.com/lw-whatever/p/11900710.html
今日推荐