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 數據的功能。