# 我们今天学习下序列化,什么是序列化呢? 将原本的字典、列表等内容转换成一个字符串的过程就叫做序列化。
# 为什么要有序列化模块: 比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给?
# 现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。 但是我们都知道,对于文件来说是没有字典这个概念的,
# 所以我们只能将数据转换成字典放到文件中。 你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢?
# 没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串, 但是你要怎么把一个字符串转换成字典呢?
# 聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。
# eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
# BUT!强大的函数有代价。安全性是其最大的缺点。 想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,
# 那么后果实在不堪设设想。
# 而使用eval就要担这个风险。 所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)
# 序列化的目的
# socketserver模块-循环接收0、以某种存储形式使自定义对象持久化;
# 2、将对象从一个地方传递到另一个地方。
# 3、使程序更具维护性。
###json模块
#socketserver模块-循环接收0、用于多种语言交互——编程语言的通用数据
#2、内置的,不需要安装的,直接导入使用
##dumps、loads、dump、load方法
###dump与load有“持久化”功能!
import json
###########################################
# dumps方法——将字典(主要)对象转换成字符串
dic = {'a1':1,'b':2}
s1 = json.dumps(dic)
print(s1,type(s1)) #{"a1": socketserver模块-循环接收0, "b": 2} <class 'str'>
# loads方法——将字符串转换成字典
d1 = json.loads(s1)
print(d1,type(d1))#{'a1': socketserver模块-循环接收0, 'b': 2} <class 'dict'>
di = '{"a1":socketserver模块-循环接收0}'
dl = '[socketserver模块-循环接收0,2,3,4,5]'
dii = json.loads(di)
dll = json.loads(dl)
print(dii,type(dii))#{'a1': socketserver模块-循环接收0} <class 'dict'>
print(dll,type(dll))#[socketserver模块-循环接收0, 2, 3, 4, 5] <class 'list'>
###########################################
# load与dump
dic1 = {'a1':1,'b':2}
json.dump(dic1,open('a1','w',encoding='utf8'))
d = json.load(open('a1','r',encoding='utf8'))
d['a1'] = 11
print(d)#{'a1': zz, 'b': 2}
###注意,手动在文件里写的话,文件里的键值如果是字符串的话必须用双引号!!!
#############################################
###总结###
# json.load()#参数:是文件句柄(w模式),将文件中字符串转换为字典
# json.dump()#参数:第一个是对象(字典),第二个是文件句柄(r模式),将字典转换为字符串写入到文件中
# json.dumps() #参数:obj(字典),将字典转换为字符串
# json.loads() #参数:字符串(类字典),将字符串转换为字典
###dumps与loads###
dic = {'k1':'v1','k2':'v2','k3':'v3'}
str_dic = json.dumps(dic) #序列化:将一个字典转换成一个字符串
print(type(str_dic),str_dic) #<class 'str'> {"k3": "v3", "k1": "v1", "k2": "v2"}
#注意,json转换完的字符串类型的字典中的字符串是由""表示的
dic2 = json.loads(str_dic) #反序列化:将一个字符串格式的字典转换成一个字典
#注意,要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示
print(type(dic2),dic2) #<class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
list_dic = [1,['a1','b','c'],3,{'k1':'v1','k2':'v2'}]
str_dic = json.dumps(list_dic) #也可以处理嵌套的数据类型
print(type(str_dic),str_dic) #<class 'str'> [socketserver模块-循环接收0, ["a1", "b", "c"], 3, {"k1": "v1", "k2": "v2"}]
list_dic2 = json.loads(str_dic)
print(type(list_dic2),list_dic2) #<class 'list'> [socketserver模块-循环接收0, ['a1', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}]
###dump与load###
f = open('json_file','w')
dic = {'k1':'v1','k2':'v2','k3':'v3'}
json.dump(dic,f) #dump方法接收一个文件句柄,直接将字典转换成json字符串写入文件
f.close()
f = open('json_file')
dic2 = json.load(f) #load方法接收一个文件句柄,直接将文件中的json字符串转换成数据结构返回
f.close()
print(type(dic2),dic2)