Inside Flask - json 處理


Inside Flask - json 處理

在處理 web api 時,json 是非常好用的數據交換格式,它結構簡單,基本上各種主流的編程語言都有良好的支持工具。

flask 中處理 json 時,對 json 加了一層包裝,從而返回一個 Response 對象。簡單的例子如下 ::

from flask import jsonify

...

@app.route('/hello')
def hello():
    result = {
        'status': 'success',
        'data': 'Hello, world!',
    }
    return jsonify(result)

flask 的 json 實現使用了 itsdangerous 中的 json 對象(來自 simplejson 或內置的 json),都在 flask/json.py 文件中。它在 json 的基礎上加一些小的修改。對於 encoder ,增加了對 date ,UUID 和 內置 __html__ 屬性(如 flask.Markup)等的處理 ::

class JSONEncoder(_json.JSONEncoder):
    ...
    def default(self, o):
        ...
        if isinstance(o, date):
            return http_date(o.timetuple())
        if isinstance(o, uuid.UUID):
            return str(o)
        if hasattr(o, '__html__'):
            return text_type(o.__html__())
        return _json.JSONEncoder.default(self, o) 

decoder 繼承 _json.JSONDecoder ,沒有修改。

除了基本的 dump / dumps / load / loads , flask 在這里還做了對 unicode 的處理和對 html 的轉換處理。它提供了兩個方法來處理 unicode 字符串 ::

def _wrap_reader_for_text(fp, encoding):
    if isinstance(fp.read(0), bytes):
        fp = io.TextIOWrapper(io.BufferedReader(fp), encoding)
    return fp
...
def _wrap_writer_for_text(fp, encoding):
    try:
        fp.write('')
    except TypeError:
        fp = io.TextIOWrapper(fp, encoding)
    return fp

對於在字節流, flask 在這里對它進行了包裝,成為 unicode 文本流,再交給 json 處理。

對於 html ,由於html 中帶有特殊的字符,需要轉換 ::

def htmlsafe_dumps(obj, **kwargs):
    rv = dumps(obj, **kwargs) \
        .replace(u'<', u'\\u003c') \
        .replace(u'>', u'\\u003e') \
        .replace(u'&', u'\\u0026') \
        .replace(u"'", u'\\u0027')
    if not _slash_escape:
        rv = rv.replace('\\/', '/')
    return rv

最后,就是我們在處理 json 常用的 jsonify 函數 ::

def jsonify(*args, **kwargs):
	indent = None
    separators = (',', ':')

    if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] and not request.is_xhr:
        indent = 2
        separators = (', ', ': ')

    if args and kwargs:
        raise TypeError('jsonify() behavior undefined when passed both args and kwargs')
    elif len(args) == 1:  # single args are passed directly to dumps()
        data = args[0]
    else:
        data = args or kwargs

    return current_app.response_class(
        (dumps(data, indent=indent, separators=separators), '\n'),
        mimetype=current_app.config['JSONIFY_MIMETYPE']
    )

jsonify 函數在 dumps 的結果基礎上,用 response_class 對結果進行了包裝,並且給返回的數據頭部的 mimetype 加上 json 類型(默認為 application/json ,可修改 JSONIFY_MIMETYPE 配置)

在使用 jsonify 函數時,需要注意只能使用 args 或 kwargs 其中一種方式,而 args 長度為1 時返回的是 args[0] 。其它模塊也使用到 json 相關的功能,如 request 中從請求加載 json 數據等,用到 load 數據的功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM