把内存中的各种数据类型的数据通过网络传送给其它机器或客户端
把内存中的各种数据类型的数据保存到本地磁盘持久化;
模块: 作用 api 注意
json 用于实现Python数据类型与通用(json)字符串之间的转换 dumps()、dump()、loads()、load() 避免dump和load次数的混乱 仅仅使用一次dunp load
序列化: encoding: 把Python对象转换成JSON字符串\
dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
反序列化: decoding: 把JSON字符串转换成python对象
loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
两个额外的方法允许我们直接将序列化后得到的json数据保存到文件中,以及直接读取文件中的json数据进行反序列化操作
序列化:将Python对象转换成json字符串并存储到文件中
dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
反序列化:读取指定文件中的json字符串并转换成Python对象
load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
JSON与Python之间数据类型对应关系
Python转JSON
Python JSON
dict Object
list, tuple array
str string
int, float, int- & float-derived Enums numbers
True true
False false
None null
JSON转Python
JSON Python
object dict
array list
string str
number(int) int
number(real) float
true True
false False
null None
说明:
Python dict中的非字符串key被转换成JSON字符串时都会被转换为小写字符串;
Python中的tuple,在序列化时会被转换为array,但是反序列化时,array会被转化为list;
当Python对象中包含tuple数据或者包含dict,且dict中存在非字符串的key时,反序列化后得到的结果与原来的Python对象是不一致的;
对于Python内置的数据类型(如:str, unicode, int, float, bool, None, list, tuple, dict)json模块可以直接进行序列化/反序列化处理;对于自定义类的对象进行序列化和反序列化时,
需要我们自己定义一个方法来完成定义object和dict之间进行转化。
pickle 用于实现Python数据类型与Python特定二进制格式之间的转换 dumps()、dump()、loads()、load()
shelve 专门用于将Python数据类型的数据持久化到磁盘,shelve是一个类似dict的对象,操作十分便捷 open()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @version : 0.0.1
# @File : configjson.py
# @Time : 2018/4/4 0004 下午 2:58
# @Site :
# @Software: PyCharm
# @Author : singebogo
# @Author_email: singbogo@163.com
# @description:
import json,demjson
dic={'name':'alvin','age':23,'sex':'male'}
print(type(dic))#<class 'dict'>
j=json.dumps(dic)
print (type(j))
f=open(u'序列化对象','w')
f.write(j) #-------------------等价于json.dump(dic,f)
f.close()
f=open(u'序列化对象')
data=json.loads(f.read())# 等价于data=json.load(f)
print (data)
json_str1 = '{"name":"test", "type":"haha", "age":123,"other":null}'
json_struct1 = json.loads(json_str1) # 个人觉得load()=JSONDecoder().decode() 反序列化 python内置数据类型 《---json的数据类型
print (json_struct1)
json_decode_struct = json.JSONDecoder().decode(json_str1)
print (json_decode_struct)
json_struct2 = {'name': 'test', 'type': 'haha', 'age':123, 'other':None} #序列化 python内置数据类型 --》json的数据类型
json_str2 = json.dumps(json_struct2)
print (json_str2)
json_encode_str = json.JSONEncoder().encode(json_struct2)
print (json_encode_str)
'''
<type 'dict'>
<type 'str'>
{u'age': 23, u'name': u'alvin', u'sex': u'male'}
{u'age': 123, u'other': None, u'type': u'haha', u'name': u'test'}
{u'age': 123, u'other': None, u'type': u'haha', u'name': u'test'}
{"age": 123, "other": null, "type": "haha", "name": "test"}
{"age": 123, "other": null, "type": "haha", "name": "test"}
'''
# 第三方库 demjson 解码和编码
data = [{ 'a':1, 'B':2, 'c':3, 'd':4, 'e':5 ,'T':23}]
json1 = demjson.encode(data)
print (json1)
json1 = '{"A":1,"b":{"f":8},"c":3,"d":4,"e":5}'
text = demjson.decode(json1)
print (text)
# 序列化
encode1 = json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)})
print (encode1)
# 序列化并对key进行排序
#sort_keys参数: 表示序列化时是否对dict的key进行排序(dict默认是无序的)
encode1 = json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, sort_keys=True)
print (encode1)
# 序列化并对key进行排序及格式化输出
#indent参数: 表示缩进的意思,它可以使得数据存储的格式变得更加优雅、可读性更强;如果indent是一个非负整数或字符串,则JSON array元素和object成员将会被以相应的缩进级别进行打印输出;如果indent是0或负数或空字符串,则将只会插入换行,不会有缩进。
print(json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, sort_keys=True, indent=4))
#separators参数: 尽管indent参数可以使得数据存储的格式变得更加优雅、可读性更强,但是那是通过添加一些冗余的空白字符进行填充的。当json被用于网络数据通信时,
# 应该尽可能的减少无用的数据传输,这样可以节省带宽并加快数据传输速度。json模块序列化Python对象后得到的json字符串中的','号和':'号分隔符后默认都会附加一个空白字符,
# 我们可以通过separators参数重新指定分隔符,从而去除无用的空白字符;
# 该参数的值应该是一个tuple(item_separator, key_separator)
# 如果indent是None,其默认值为(', ', ': ')
# 如果indent不为None,则默认值为(',', ': ')
# 我们可以通过为separator赋值为(',', ':')来消除空白字符
encode1 = json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)})
print (encode1)
encode1 = json.dumps({'a':'str', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g':(4, 5, 6)}, separators=(',',':'))
print (encode1)
# 反序列化
decode1 = json.loads('{"a": "str", "c": true, "b": 11.1, "e": 10, "d": null, "g": [4, 5, 6], "f": [1, 2, 3]}')
print (decode1)
decode1 = json.loads('{"a":"str","c":true,"b":11.1,"e":10,"d":null,"g":[4,5,6],"f":[1,2,3]}')
print (decode1)
#需要说明的是: 如果试图使用相同的fp重复调用dump()函数去序列化多个对象(或序列化同一个对象多次),将会产生一个无效的JSON文件,也就是说对于一个fp只能调用一次dump()。
# 序列化到文件中
with open('test.json', 'w') as fp:
json.dump({'a': 'str中国', 'c': True, 'e': 10, 'b': 11.1, 'd': None, 'f': [1, 2, 3], 'g': (4, 5, 6)}, fp, indent=4)
# 反序列化文件中的内容
with open('test.json', 'r') as fp:
json.load(fp)
#自定义数据类型的序列化/反序列化
#要实现自定义数据类型的序列化与反序列化有两种方式:
# 1、通过转换函数实现
# 2、通过继承JSONEncoder和JSONDecoder类实现
class Student(object):
def __init__(self, name, age, sno):
self.name = name
self.age = age
self.sno = sno
def __repr__(self):
return 'Student [name: %s, age: %d, sno: %d]' % (self.name, self.age, self.sno)
#直接调用dumps()方法会引发TypeError错误:
stu = Student('Tom', 19, 1)
print(stu)
#TypeError: Student [name: Tom, age: 19, sno: 1] is not JSON serializable
# stu对象不可以被序列化为JSON格式的数据。那么我们分别通过“编写转换函数” 和 “继承JSONEncoder和JSONDecoder类” 来实现对这个自定义数据类型的JSON序列化和反序列化
# json.dumps(stu)
#方法1:编写转换函数
#这个转换函数是要完成的是Python对象(不是JSON对象)与dict之间的相互转换,且序列化时转换过程是“Python对象 --> dict --> JSON object”,反序列化的过程是“JSON object -> dict --> Python对象”
def obj2dict(obj):
d = {}
d['__class__'] = obj.__class__.__name__
d['__module__'] = obj.__module__
d.update(obj.__dict__)
return d
def dict2obj(d):
if '__class__' in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
class_ = getattr(module, class_name)
args = dict((key.encode('ascii'), value) for key, value in d.items())
instance = class_(**args)
else:
instance = d
return instance
# objdict = obj2dict(stu)
# json.dumps(obj2dict(stu)
json.dumps(stu, default=obj2dict)
#反序列化测试:
json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}')
dict2obj(json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}'))
json.loads('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}', object_hook=dict2obj)
#方法2:继承JSONEncoder和JSONDecoder实现子类
class MyJSONEncoder(json.JSONEncoder):
def default(self, obj):
d = {}
d['__class__'] = obj.__class__.__name__
d['__module__'] = obj.__module__
d.update(obj.__dict__)
return d
class MyJSONDecoder(json.JSONDecoder):
def __init__(self):
json.JSONDecoder.__init__(self, object_hook=self.dict2obj)
def dict2obj(self, d):
if '__class__' in d:
class_name = d.pop('__class__')
module_name = d.pop('__module__')
module = __import__(module_name)
class_ = getattr(module, class_name)
args = dict((key.encode('ascii'), value) for key, value in d.items())
instance = class_(**args)
else:
instance = d
return instance
#序列化测试:
stu = Student('Tom', 19, 1)
# 方式一:直接调用子类MyJSONEncoder的encode()方法进行序列化
print (MyJSONEncoder().encode(stu))
print ( MyJSONEncoder(separators=(',', ':')).encode(stu))
# 方式二:将子类MyJSONEncoder作为cls参数的值传递给json.dumps()函数
print json.dumps(stu, cls=MyJSONEncoder)
print (json.dumps(stu, cls=MyJSONEncoder, separators=(',', ':')))
#反序列化测试:
print (MyJSONDecoder().decode('{"sno": 1, "__module__": "__main__", "age": 19, "__class__": "Student", "name": "Tom"}'))
#说明: 经过测试发现MyJSONDecoder().decode(JSON_STR) 和 json.loads(JSON_STR, object_hook=dict2obj) 只能在Python 2.7上正确执行,
# 在Python 3.5上无法正确执行;而 json.loads(JSON_STR, cls=MyJSONDecoder) 无论在Python 2.7还是在Python 3.5上都无法正确执行。
# 这说明json模块对于自定义数据类型的反序列化支持还是比较有限的,但是我们也可以通过json.loads(JSON_STR)函数,不指定cls参数来得到一个dict对象,然后自己完成dict到object的转换。
#继承JSONEncoder实现序列化时还有一个额外的作用,就是可以通过iterencode()方法把一个很大的数据对象分多次进行序列化,这对于网络传输、磁盘持久化等情景非常有用
for chunk in MyJSONEncoder().iterencode(stu):
print(chunk)
#大数据对象序列化网络传输伪代码:
# for chunk in JSONEncoder().iterencode(bigobject):
# mysocket.write(chunk)