大家好,这里是米洛,一个想和大家一起分享测试开发
相关的技术,面试经验和成长经历的博主!
几乎每个人都用过json序列化Python对象,比如:
import json data = {"code": 101, "status": True} result = json.dumps(data)
大家应该也都知道,要想中文被正常解析,还得传入这样的参数:
result = json.dumps(data, ensure_ascii=False)
那么你知道,json.dumps方法还有很多其他参数等你去研究吗?
故事
榜一大哥,他最近在研究MongoDB,他使用pymongo,查出来了一个mongo数据对象,在Python中的值是这样的:
result = { "_id": ObjectId("60f7ff90d013bd74e50c5a95"), "name": "hehe", "student": False }
榜一大哥想着,能把这个数据给写到txt里,于是他想起来json.dumps先把数据序列化,再操作文件write方法写入数据。
print(json.dumps(result))
可是现实给了他一记重拳!
image
因为MongoDB默认的_id
字段是Object类型,在json中没有与之对应的数据。
至于为什么其他数据能对应,因为他们从Python到JSON有对应数据转换规则
:
image
其实不止是ObjectId,我们常用的datetime对象
也是如此。
小技巧
解决问题很容易,既然没有规则,那咱们就创造规则
。
ObjectId实际上是一串字符串,而datetime我们常用字符串如2001-02-01 11:11:11
这样的字符串表示。
dumps方法为我们提供了自定义类,专门解析表里面没有的(或者我们自定义的)数据类型。
class MyEncoder(JSONEncoder): def default(self, o): if isinstance(o, datetime): return o.strftime("%Y-%m-%d %H:%M:%S") if isinstance(o, ObjectId): return o.__str__() return JSONEncoder.default(self, o)
我们继承json.JSONEncoder类,重写default
方法,如果数据类型是datetime,我们则调用strftime方法,让它变成字符串,而对于ObjectId,我们直接将之转为str即可。
修改后的完整代码:
import json from datetime import datetime from json import JSONEncoder from bson import ObjectId class MyEncoder(JSONEncoder): def default(self, o): if isinstance(o, datetime): return o.strftime("%Y-%m-%d %H:%M:%S") if isinstance(o, ObjectId): return o.__str__() return JSONEncoder.default(self, o) result = { "_id": ObjectId(), "name": "hehe", "create_time": datetime.now(), "student": False, } print(json.dumps(result, cls=MyEncoder))
image
编写好类以后,把类传递给cls参数就可以达到目的。
肥肠好用!!!
这个是送的
榜一大哥觉得一行显示不好看,想格式化
一下该怎么做呢?
print(json.dumps(result, cls=MyEncoder, indent=4))
只需要加一个indent参数即可,一般可以用2或者4,看看符不符合榜一大哥的口味。
image