bigywater.tech
Flask · 33

Form Data 与 JSON Body

同样是 POST,表单和 JSON 在 Flask 里分别从哪读?Content-Type 不对会怎样?JSON 非法是 400 还是 415?表单太大会被拒吗?这篇逐个试。

415
Content-Type 不是 JSON 时 get_json() 的状态码
400
JSON 非法或正文为空时 get_json() 的状态码
1000
MAX_FORM_PARTS 的默认值

四种 Content-Type

实测 · 本机执行输出
  application/x-www-form-urlencoded    form={'a': ['1'], 'b': ['x', 'y']} files=[] json=None data_len=0
  multipart/form-data                  form={'a': ['1']} files=['f'] json=None data_len=0
  application/json                     form={} files=[] json={'a': 1} data_len=8
  text/plain                           form={} files=[] json=None data_len=12
  (data_len 为 0 表示请求体已经被 form / files 解析消耗了,get_data() 拿不到)

上一篇:Query String 参数解析;下一篇:request.args、request.form、request.json。

get_json() 的各种情况

实测 · 本机执行输出
  Content-Type: application/json + 合法 JSON → 200 {'json': {'a': 1}}
  Content-Type: application/json + 非法 JSON → 400 {'error': 'BadRequest', 'msg': '400 Bad Request: The browser (or proxy) sent a request that this server could not understand.'}
  Content-Type: text/plain + 合法 JSON       → 415 {'error': 'UnsupportedMediaType', 'msg': "415 Unsupported Media Type: Did not attempt to load JSON data because the request Content-Type was not 'application/json"}
  没有 Content-Type                          → 415 {'error': 'UnsupportedMediaType', 'msg': "415 Unsupported Media Type: Did not attempt to load JSON data because the request Content-Type was not 'application/json"}
  application/json + 空正文                   → 400 {'error': 'BadRequest', 'msg': '400 Bad Request: The browser (or proxy) sent a request that this server could not understand.'}
  application/vnd.api+json                 → 200 {'json': {'a': 1}}
  application/json; charset=utf-8 + 中文     → 200 {'json': {'名': '张三'}}
  text/plain + force=True → {'force': {'a': 1}, 'silent_after_force': {'a': 1}, 'silent_first': None}

多值字段

实测 · 本机执行输出
  form = {'single': ['x'], 'tags': ['a', 'b', 'c']}
  form["tags"] = a | form.getlist("tags") = ['a', 'b'] | form.get("none") = None

表单大小限制

实测 · 本机执行输出
  默认值:MAX_FORM_MEMORY_SIZE = 500000 | MAX_FORM_PARTS = 1000
  MAX_FORM_PARTS=5 时发 10 个 multipart 字段 → 413
  MAX_FORM_MEMORY_SIZE=100 时发 500 字节的表单字段 → 200
  同样 500 字节,multipart 形式 → 413

JSON 的类型

实测 · 本机执行输出
  JSON 往返: {'n': 1, 'nested': {'a': [1, 2]}, 'none': None, 'ok': True} | 类型: {'n': 'int', 'nested': 'dict', 'none': 'NoneType', 'ok': 'bool'}

分步演示

请求体解析
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.7 / Flask 3.1.3 / Werkzeug 3.1.9 / Jinja2 3.1.6 / SQLAlchemy 2.1.1 / gunicorn 26.2.0(都装在自己的虚拟环境里);大多数实验用 Flask 的 test_client(直接调用 WSGI 应用,不经过网络),需要真实 HTTP 时另起 gunicorn 或开发服务器(端口 9600 以上,本机 127.0.0.1);计时用 time.perf_counter,数字每次运行会有小幅抖动
    • 没有验证:chunked 请求体的 JSON、超大 JSON(MAX_CONTENT_LENGTH,见第 37 篇)、get_json 的 cache 参数在多次调用下的差别、非 UTF-8 编码的 JSON、urlencoded 为什么没有触发 MAX_FORM_MEMORY_SIZE(没有深究)
    京ICP备2026067502号-1京公网安备11010502063487号