美化JSON响应¶
要使JSON响应更具人类可读性,可能需要美化输出。默认情况下,Falcon的 JSONHandler
配置为最大限度地减少序列化开销。但是,您只需提供所需的 dumps
参数:
import functools
import json
from falcon import media
json_handler = media.JSONHandler(
dumps=functools.partial(json.dumps, indent=4, sort_keys=True),
)
现在可以替换默认值 application/json
response media handlers
用这个定制的 json_handler
使应用程序的JSON响应更漂亮(另请参见: 替换默认处理程序 )
备注
另一种调试方法是在客户端美化JSON,例如,流行的 HTTPie 默认情况下是这样做的。另一种选择是简单地通过管道将JSON响应传输到 jq 。
如果调试案例允许,则应首选客户端方法,因为它既不会增加服务器端的性能开销,也不需要任何定制工作。
支持可选缩进¶
互联网媒体类型(内容类型)协商是表达资源表示偏好的规范方式。虽然不是 application/json
媒体类型标准、一些框架(如Django睡觉框架)和服务支持使用 indent
内容类型参数。本食谱将这样的参数是否添加了“新功能”的解释留给了读者 RFC 6836, Section 4.3 。
假设我们想要添加JSON indent
对Falcon应用程序的支持,这可以通过 custom media handler :
import cgi
import json
import falcon
class CustomJSONHandler(falcon.media.BaseHandler):
MAX_INDENT_LEVEL = 8
def deserialize(self, stream, content_type, content_length):
data = stream.read()
return json.loads(data.decode())
def serialize(self, media, content_type):
_, params = cgi.parse_header(content_type)
indent = params.get('indent')
if indent is not None:
try:
indent = int(indent)
# NOTE: Impose a reasonable indentation level limit.
if indent < 0 or indent > self.MAX_INDENT_LEVEL:
indent = None
except ValueError:
# TODO: Handle invalid params?
indent = None
result = json.dumps(media, indent=indent, sort_keys=bool(indent))
return result.encode()
此外,我们还需要实现内容类型协商来接受缩进的JSON内容类型以进行响应序列化。最低限度的示例使用如下所述的中间件组件: 内容类型协商 。
为安装此处理程序后 application/json
响应媒体,以及添加协商中间件,我们应该能够产生缩进的JSON输出(构建在首页之上 QuoteResource
示例):
$ curl -H 'Accept: application/json; indent=4' http://localhost:8000/quote
{
"author": "Grace Hopper",
"quote": "I've always been more interested in the future than in the past."
}
警告
在公共API中实现这一点可能被视为一种不必要的攻击手段。
在发生拒绝服务攻击的情况下,您将为攻击者提供一种增加CPU负载的便捷方法,只需请求缩进输出即可,尤其是在有大型JSON响应可用的情况下。
此外,使用缩进和不使用缩进重播完全相同的请求可能会揭示对计时攻击有用的信息,特别是如果攻击者能够猜测所使用的JSON模块的确切风格。