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 数据的功能。