flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]目录1.看源码2、重写默认的default函数,实现自己的序列化机制3、把对象转化成字典3.1__dict__的方式3.2、定义keys和__getitem__的方式4、最终的代码实现5、关于default函数的其他知识1.看源码打开site-package,flask,json,__init__.pyjsonify回去调用default()函数,我们…

大家好,又见面了,我是你们的朋友全栈君。

目录

1.看源码

2、重写默认的default函数,实现自己的序列化机制

3、把对象转化成字典

3.1 __dict__的方式

3.2、定义keys和__getitem__的方式

4、最终的代码实现

5、关于default函数的其他知识


1.看源码

打开site-package,flask,json,__init__.py

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

jsonify回去调用default()函数,我们最关心的就是重写default方法

我们是不是调用jsonify就一定会调用default呢?答案:不是!

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

发现如上图所示,并没有进入jsonify的default方法里,而是直接把字典给序列化出来了。

那么什么时候会调用default呢?

结论:如果flask知道如何序列化你传入进来的数据结构的时候,是不会调用default,因为知道如何序列化就直接帮我们序列化了,但是如果我们要序列化一个对象,是我们的user模型,flask默认是不知道怎么去序列化这个模型的,那么就会去调用default函数,为什么会这样的,原因就在于flask不知道怎么序列化,但是它会给我们一个途径,让我们来指明这个数据结构应该怎么序列化,换句话说,default函数最主要的就是我们需要在内部把不能序列化的结构转化为可以序列化的结构,比如我们传入进来的是一个user,user是不能序列化的,但是如果我们可以把user转化成字典,字典是可以序列化的,那么这样就能完成user对象的序列化了,虽然user作为一个模型他不能序列化,但是我们可以把他的信息读取出来,转化为一个字典,从而保证我们整个序列化的成功执行。可以看到default里面的源码,传入的user对象既不是datetime也不是date、uuid.UUID、__html__,所以最后会抛出一个异常

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

所以我们要在default中把不能序列化的user转化成可以序列化的格式。

所以我们继承,然后重写default方法,在重写的函数中实现user的可序列化就OK了

2、重写默认的default函数,实现自己的序列化机制

我们不要直接修改源码,要在外部继承JSONEncoder,然后在用自己的方法覆盖原来的default方法。

from flask import Flask, jsonify
class hehe:
    name = 'zhangsan'
    age = 18

app = Flask(__name__)
ctx = app.app_context()
ctx.push()
# 上面是解决上下文对象的异常RuntimeError: Working outside of application context.

a = hehe()
print(a)
jsonify(a)  # TypeError: Object of type 'hehe' is not JSON serializable

可以看到上图代码报错不能序列化a对象,所以我们要在外部继承JSONEncoder,然后在用自己的方法覆盖原来的default方法。

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

可以看到即使按照上图所示写,flask还是没有调用我们自己定义的default,所以我们还要在flask里面替换一下

from flask import Flask as _Flask, jsonify
from flask.json import JSONEncoder as _JSONEncoder


class JSONEncoder(_JSONEncoder):

    def default(self, o):
        pass


class Flask(_Flask):
    json_encoder = JSONEncoder


class hehe():
    name = 'zhangsan'
    age = 18


app = Flask(__name__)
ctx = app.app_context()
ctx.push()
# 上面是解决上下文对象的异常RuntimeError: Working outside of application context.

a = hehe()
print(a)

jsonify(a)  # 不报错了

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

可以看到flask把我们实例化的hehe类当做参数o传递了进来,有两个属性

3、把对象转化成字典

3.1 __dict__的方式

现在我们要把对象转化成字典,因为字典是可以被序列化的, 但是对象不行。我们想到了对象的__dict__内置方法,但是发现没有得到任何的结果,输出的是一个空的json对象。

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

这是因为我们在hehe类里面定义的是类的变量而不是实例的变量。类的变量是不会被存放到对象的__dict__当中的。所以加入一个实例变量的时候就有值了(如下图)

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

所以我们看到这种方式是可以的,但是我们想把无论类变量还是实例变量都像把它直接序列化,我们就需要用下面的方法把所有的都转成字典

3.2、定义keys和__getitem__的方式

python 对象转字典及序列化对象相关问题,__dict__!!!!必看,多坑

class D:
    name = 'zhangsan'
    age = 18
 
    def __init__(self):
        self.sex = '男'
 
    def keys(self):
        return ('name', 'sex')
 
    def __getitem__(self, item):
        return getattr(self, item)
 
 
d = D()
print(d.__dict__)  # {'sex': '男'}
print(dict(d))  # {'name': 'zhangsan', 'sex': '男'} 如果注销了getitem方法就会报错TypeError: 'D' object is not iterable

4、最终的代码实现

from flask import Flask as _Flask, jsonify
from flask.json import JSONEncoder as _JSONEncoder


class JSONEncoder(_JSONEncoder):
    def default(self, o):
        if hasattr(o, 'keys') and hasattr(o, '__getitem__'):
            print(dict(o))
        else:
            print("不能序列化对象")


class Flask(_Flask):
    json_encoder = JSONEncoder


class hehe:
    name = 'zhangsan'
    age = 18

    def __init__(self):
        self.sex = '男'

    def keys(self):
        return ('name', 'sex')

    def __getitem__(self, item):
        return getattr(self, item)


app = Flask(__name__)
ctx = app.app_context()
ctx.push()
# 上面是解决上下文对象的异常RuntimeError: Working outside of application context.
a = hehe()
print(a)  # <__main__.hehe object at 0x7f0aed3e1e10>
jsonify(a)  # {'name': 'zhangsan', 'sex': '男'}

5、关于default函数的其他知识

default函数是被递归调用的,之所以我们没看到被递归调用是因为我们定义的类都太简单了,如果对象下面的某个属性是另外一个对象的情况

只要遇到不能序列化的对象,都会传入default里面让我们来解决,

例如下面所示default调用了两次:

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

flask jsonify之序列化时的default函数、jsonify序列化自定义对象[通俗易懂]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/142301.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Quartz任务中调用Spring容器中bean及动态调度任务-SchedulerFactoryBean「建议收藏」

    Quartz任务中调用Spring容器中bean及动态调度任务-SchedulerFactoryBean「建议收藏」Quartz是开源任务调度框架中的翘首,它提供了强大任务调度机制,同时保持了使用的简单性。Quartz允许开发人员灵活地定义触发器的调度时间表,并可以对触发器和任务进行关联映射。此外,Quartz提供了调度运行环境的持久化机制,可以保存并恢复调度现场,即使系统因故障关闭,任务调度现场数据并不会丢失。此外,Quartz还提供了组件式的侦听器、各种插件、线程池等功能。Spring为…

    2022年5月23日
    99
  • 轻松搞懂【TF-IDF、word2vec、svm、cnn、textcnn、bilstm、cnn+bilstm、bilstm+attention实现】英文长文本分类[通俗易懂]

    轻松搞懂【TF-IDF、word2vec、svm、cnn、textcnn、bilstm、cnn+bilstm、bilstm+attention实现】英文长文本分类[通俗易懂]项目来源:https://www.kaggle.com/c/word2vec-nlp-tutorial/之前我写过几篇博客:就这?word2vec+BiLSTM、TextCNN、CNN+BiLSTM、BiLSTM+Attention实现中英文情感分类代码详解就这?word2vec+SVM(支持向量机)实现中英文情感分类代码详解这两篇博客主要是基于中文进行情感分类的,那么本篇博客,我会以这个kaggle项目来介绍如何实现英文长文本情感分类。1实验数据本次数据集来源于kaggle项目“Bago

    2022年6月28日
    30
  • c语言运行后电脑很卡,如何让电脑提速,电脑卡是什么原因?

    c语言运行后电脑很卡,如何让电脑提速,电脑卡是什么原因?前言昨天的文章被限制了,正在申诉刚好最近有网友问小编这样一个问题:花了六千买的独显笔记本,用了才一年就卡的不行了,请问电脑卡是什么原因?小编对电脑还算颇有研究,看了网友电脑配置并不算低,导致电脑卡的原因主要在于系统优化与一些硬件方面的问题,下面小编就来说说如何让电脑提速。正文电脑卡是什么原因?导致电脑卡的原因有很多,综合来看,无非就是软件与硬件的问题。其中,软件层面主要是系统优化,硬件方面则主要是…

    2022年6月7日
    40
  • Dirty deeds done dirt cheap_centos 8 stratis

    Dirty deeds done dirt cheap_centos 8 stratis文章目录[隐藏]TweakSwaponCentOS7TweakSwaponCentOS7Swapisquiteimportantonasmallvirtualmachinebutalsoonlargeservers.Ifyouhaven’tenabledSwapyetyoushouldcheckthefollowingguideh…

    2022年10月8日
    4
  • java中list,set,map集合的区别,及面试要点[通俗易懂]

    java中list,set,map集合的区别,及面试要点[通俗易懂](图一)1.面试题:你说说collection里面有什么子类。(其实面试的时候听到这个问题的时候,你要知道,面试官是想考察List,Set)正如图一,list和set是实现了collection接口的。(…

    2022年5月11日
    102
  • 卷积神经网络(3)—-经典网络

    卷积神经网络(3)—-经典网络

    2021年6月17日
    150

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号