我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Flask自定义序列化超详细讲解

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Flask自定义序列化超详细讲解

1、问题溯源

重点就是一个Flask.make_response,这里会做请求的响应的处理。

里面行代码:

elif isinstance(rv, dict):
     rv = jsonify(rv)

rv是我需要返回的响应:

{
	'msg': [
        {'roleName': 'guest', 'access_list':[<accessName root>]},
        {'roleName': 'admin', 'access_list': [...]}
        ], 
    'error_no': 0
}

rv是一个字典,但是msg的里面有部分东西无法序列化,jsonify里面返回如下。

return current_app.response_class(
        f"{dumps(data, indent=indent, separators=separators)}\n",
        mimetype=current_app.config["JSONIFY_MIMETYPE"],
    )

里面的data就是上面交道的类似json的数据(不是json,实际是对象)。

接下来:调用了flask下的自带的一个json库。

代码片段: M-1

_dump_arg_defaults(kwargs, app=app)
return _json.dumps(obj, **kwargs)

代码片段: M -2

if cls is None:
        cls = JSONEncoder
return cls(
        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
        separators=separators, default=default, sort_keys=sort_keys,
        **kw).encode(obj)

这里的obj的:

{'msg': [{...}, {...}], 'error_no': 0}

就是我们之前讲到的东西。

代码片段: M-4,这个是内置的json库的default方法。内置的没有实现序列化,所以需要自己在某个步骤接入到这个序列化的过程。

def default(self, o):
        """Implement this method in a subclass such that it returns
        a serializable object for ``o``, or calls the base implementation
        (to raise a ``TypeError``).
        For example, to support arbitrary iterators, you could
        implement default like this::
            def default(self, o):
                try:
                    iterable = iter(o)
                except TypeError:
                    pass
                else:
                    return list(iterable)
                # Let the base class default method raise the TypeError
                return JSONEncoder.default(self, o)
        """
        raise TypeError(f'Object of type {o.__class__.__name__} '
                        f'is not JSON serializable')

o在这里就是AccessOrm是实例对象,所以他报错说这个:

Object of type AccessOrm is not JSON serializable

归因:就是flask没有自带实现对类的序列化

解决: 就是通过flask的机制,绑定一个序列化类。

2、flask序列化

flask代码里面写了:

class JSONEncoder(_json.JSONEncoder):
    """The default JSON encoder. Handles extra types compared to the
    built-in :class:`json.JSONEncoder`.
    -   :class:`datetime.datetime` and :class:`datetime.date` are
        serialized to :rfc:`822` strings. This is the same as the HTTP
        date format.
    -   :class:`uuid.UUID` is serialized to a string.
    -   :class:`dataclasses.dataclass` is passed to
        :func:`dataclasses.asdict`.
    -   :class:`~markupsafe.Markup` (or any object with a ``__html__``
        method) will call the ``__html__`` method to get a string.
    Assign a subclass of this to :attr:`flask.Flask.json_encoder` or
    :attr:`flask.Blueprint.json_encoder` to override the default.
    """

在片段代码M-1中:

_dump_arg_defaults(kwargs, app=app)

函数内容如下:

def _dump_arg_defaults(
    kwargs: t.Dict[str, t.Any], app: t.Optional["Flask"] = None
) -> None:
    """Inject default arguments for dump functions."""
    if app is None:
        app = current_app
    if app:
        cls = app.json_encoder #app的json_encoder
        bp = app.blueprints.get(request.blueprint) if request else None  # type: ignore
        if bp is not None and bp.json_encoder is not None:
            cls = bp.json_encoder #这里设置蓝图的json_encoder,蓝图的优先级高于app.json_encoder
        # Only set a custom encoder if it has custom behavior. This is
        # faster on PyPy.
        if cls is not _json.JSONEncoder:
            kwargs.setdefault("cls", cls)
        kwargs.setdefault("cls", cls)
        kwargs.setdefault("ensure_ascii", app.config["JSON_AS_ASCII"])
        kwargs.setdefault("sort_keys", app.config["JSON_SORT_KEYS"])
    else:
        kwargs.setdefault("sort_keys", True)
        kwargs.setdefault("cls", JSONEncoder)

3、解决方法

使用自带的序列化类

在入口函数setup.py中写入

from flask import Flask
from flask.json import JSONEncoder
from config import Config,LogConfig
from db import init_db
from scripts import user_cli
from flask_bcrypt import Bcrypt
from utils import RedisPool
class ExtendJSONEncoder(JSONEncoder):
    def default(self, o):
        if getattr(o,'toJson'):
            return o.toJson(o)
        else:
            return super().default(o)
flask_bcrypt = Bcrypt()
def create_app():
    Flask.json_encoder = ExtendJSONEncoder 
    #之前在with app.app_context()
    #或者在app实例化之后,修改app的JSONEncoder 都没成功,这里简单粗暴一点,直接修改Flask的。
    app = Flask(__name__)
    app.config.from_object(Config)
    LogConfig.openLog()
    from utils import initException,initBeforeRequestHandle
    with app.app_context():
        init_db(app)
        RedisPool(app)
        initException(app)
        initBeforeRequestHandle(app)
        flask_bcrypt.init_app(app)
        app.cli.add_command(user_cli)
        import controller
        for bp in controller.__all__:
            app.register_blueprint(controller.__dict__[bp])
    return app

这时候,我的orm类需要一个toJson方法。

class AccessOrm(Base):
    __tablename__ = 'access'
    id = Column(Integer, primary_key=True)
    accessName = Column(String(255), nullable=True)
    def __repr__(self) -> str:
        return "<accessName {}>".format(
            self.accessName,
            )
    def toJson(self,o):
        return {
            'accessName': o.accessName,
        }

到此这篇关于Flask自定义序列化超详细讲解的文章就介绍到这了,更多相关Flask序列化内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Flask自定义序列化超详细讲解

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Flask自定义序列化超详细讲解

序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化。php将数据序列化和反序列化会用到两个函数:serialize将对象格式化成有序的字符串、unserialize将字符串还原成原来的对象
2022-11-13

PHPsession反序列化漏洞超详细讲解

这篇文章主要介绍了PHP session反序列化漏洞,php session反序列化漏洞存在的原因是当序列化session和读取反序列化字符时采用的序列化选择器不一样时,处理的方法不一样
2023-02-16

SpringBoot工程启动顺序与自定义监听超详细讲解

这篇文章主要介绍了SpringBoot工程启动顺序与自定义监听,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2022-11-13

SpringBoot自定义MessageConvert详细讲解

正在学习SpringBoot,在自定义MessageConverter时发现:为同一个返回值类型配置多个MessageConverter时,可能会发生响应数据格式错误,或406异常(客户端无法接收相应数据)。在此记录一下解决问题以及追踪源码的过程
2023-01-11

php反序列化之魔术方法超详细讲解

序列化其实就是将数据转化成一种可逆的数据结构,自然,逆向的过程就叫做反序列化。php将数据序列化和反序列化会用到两个函数:serialize将对象格式化成有序的字符串、unserialize将字符串还原成原来的对象
2022-11-13

C++BoostMetaStateMachine定义状态机超详细讲解

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-12-08

fastjson序列化时间自定义格式示例详解

这篇文章主要为大家介绍了fastjson序列化时间自定义格式示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-18

python魔法方法-自定义序列详解

自定义序列的相关魔法方法允许我们自己创建的类拥有序列的特性,让其使用起来就像 python 的内置序列(dict,tuple,list,string等)。 如果要实现这个功能,就要遵循 python 的相关的协议。所谓的协议就是一些约定内容
2022-06-04

Rust结构体的定义与实例化详细讲解

结构体是一种自定义的数据类型,它允许我们将多个不同的类型组合成一个整体。下面我们就来学习如何定义和使用结构体,并对比元组与结构体之间的异同,需要的可以参考一下
2022-12-12

深入解析SpringBoot默认JSON解析器及自定义字段序列化策略

SpringBoot​ 中对依赖都做了很好的封装,可以看到很多 spring-boot-starter-xxx​系列的依赖,这是 SpringBoot​ 的特点之一,不需要人为去引入很多相关的依赖了,starter-xxx​ 系列直接都包含

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录