8 json序列化以及序列化非默认类型
1 简介
json格式(JavaScript Object Notation的缩写)是一种用于交换数据的文本格式。每个JSON对象,就是一个值。
要么是简单类型的值,要么是复合类型的值,但是只能是一个值,不能是两个或更多的值。这就是说,每个JSON文档只能包含一个值。
2 JSON对值的类型和格式的规定
1. 支持类型 :dict |list| int |float| bool| str| null 2. 支持格式 :{}和[]的组合,{}存放双列信息(类比字典) ,[]存放单列信息(类比列表) 3. {}的key必须是字符串,并且用""包裹(双引号) 4. 字符串必须使用双引号表示,不能使用单引号。 5. 对象的键名必须放在双引号里面。 6. 数组或对象最后一个成员的后面,不能加逗号。
3 序列化与反序列化
序列化 将对象转化为字符串
反序列化 将字符串转化为对象
# 序列化:将对象转换为字符串 #json.dumps(): 将 Python 对象编码成 JSON 字符串 # json.dump(): 将Python对象序列化为json字符串后写入文件 obj = {'name': 'Owen', "age": 18, 'height': 180, "gender": "男"} r1 = json.dumps(obj, ensure_ascii=False) # 取消默认ascii编码,同该文件的编码 utf-8 py3默认,py2规定文件头 print(r1) # {"name": "Owen", "age": 18, "height": 180, "gender": "男"} with open('1.txt','w',encoding='utf-8') as wf: # 若没有1.txt会创建 json.dump(obj,wf,ensure_ascii=False) # 将转化后的json字符串{"name": "Owen", "age": 18, "height": 180, "gender": "男"}写入1.txt中 # 反序列化:将字符串转换为对象 # json.load() 读取文件中json形式的字符串元素转化为Python对象 # json.loads() 将已编码的 JSON 字符串解码为 Python 对象 json_str = '{"name": "Owen", "age": 18, "height": 180, "gender": "男"}' r2 = json.loads(json_str, encoding='utf-8') # 默认跟当前文件被解释器执行的编码走 print(r2, type(r2)) with open('1.txt', 'r', encoding='utf-8') as rf: r3 = json.load(rf) print(r3, type(r3))
4 python与json的对应关系
可以在json.JSONEncoder找到源码
"""Extensible JSON <http://json.org> encoder for Python data structures.
Supports the following objects and types by default:
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
To extend this to recognize other objects, subclass and implement a
``.default()`` method with another method that returns a serializable
object for ``o`` if possible, otherwise it should call the superclass
implementation (to raise ``TypeError``).
"""
5 json序列化本不支持的类型
有两种方式 第一种就是将不支持的类型转换为json支持的类型 第二种就是源码当中告知的继承源码中的类 自己重写一个类
案例
import json from datetime import datetime,date res = {'c1':datetime.now(),'c2':date.today()} # print(json.dumps(res)) # 报错如下 ''' 报错 in default o.__class__.__name__) TypeError: Object of type 'datetime' is not JSON serializable ''' ''' 源码 def 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): def default(self, o): raise TypeError("Object of type '%s' is not JSON serializable" % o.__class__.__name__) ''' ''' 通过源码可知 主要的default方法报的错 那么只需要重写default方法 实现自己想要的 然的功能 然后继承json.JSONEncoder就可以了 ''' class MyJson(json.JSONEncoder): def default(self, o): if isinstance(o,datetime): return o.strftime(("%Y-%m-%d %X")) elif isinstance(o,date): return o.strftime(("%Y-%m-%d")) else: return super().default(self,o) res = {'c1':datetime.now(),'c2':date.today()} print(json.dumps(res,cls=MyJson)) # {"c1": "2021-03-04 22:49:38", "c2": "2021-03-04"}