广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Flask自定义序列化超详细讲解
  • 782
分享到

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

Flask序列化Flask自定义序列化 2022-11-13 19:11:41 782人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录1、问题溯源2、flask序列化3、解决方法1、问题溯源 重点就是一个Flask.make_response,这里会做请求的响应的处理。 里面行代码: elif isinsta

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序列化内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Flask自定义序列化超详细讲解

本文链接: https://www.lsjlt.com/news/171155.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

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

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作