社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

每天一个Python小技巧(3)

米洛丶 • 4 年前 • 271 次点击  
阅读 33

每天一个Python小技巧(3)

每天一个Python小技巧(3)之JSON序列化

大家好,这里是米洛,一个想和大家一起分享测试开发相关的技术,面试经验和成长经历的博主!

欢迎大家关注我的公众号: 测试开发坑货


几乎每个人都用过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))
复制代码

可是现实给了他一记重拳!

因为MongoDB默认的_id字段是Object类型,在json中没有与之对应的数据。

至于为什么其他数据能对应,因为他们从Python到JSON有对应数据转换规则:

其实不止是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))
复制代码

编写好类以后,把类传递给cls参数就可以达到目的。

肥肠好用!!!

这个是送的

榜一大哥觉得一行显示不好看,想格式化一下该怎么做呢?

print(json.dumps(result, cls=MyEncoder, indent=4))
复制代码

只需要加一个indent参数即可,一般可以用2或者4,看看符不符合榜一大哥的口味。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/117470
 
271 次点击