Flask中request.get_json()返回None的根本原因是Content-Type未设为application/json;若混用表单类型(如multipart/form-data),需手动从request.form或request.get_data()提取JSON字符串再解析。

Flask里request.get_json()返回None,但明明发了JSON
根本原因通常是Content-Type没设对。Flask默认只在Content-Type: application/json时解析JSON体;如果混用了表单字段(比如multipart/form-data或application/x-www-form-urlencoded),request.get_json()直接返回None,哪怕请求体里确实塞了JSON字符串。
常见错误场景:前端用fetch发一个含file字段和metadata JSON字符串的表单——此时Content-Type是multipart/form-data,Flask压根不触发JSON解析逻辑。
- 检查
request.headers.get('Content-Type'),确认是否为application/json - 若非纯JSON,别依赖
request.get_json(),改用request.get_data(as_text=True)手动解析 - 注意
as_text=True会自动处理编码,但若原始数据含二进制(如文件+JSON混合),需用as_text=False再按需解码
如何安全地从request.data里提取JSON部分
当Content-Type不是application/json,但你确实在请求体开头或某个字段里写了JSON(例如把JSON字符串作为form的一个字段值),就得手动剥离解析。
典型做法是先读原始字节,再尝试JSON加载,同时捕获异常:
立即学习“Python免费学习笔记(深入)”;
try:
raw = request.get_data(as_text=True)
data = json.loads(raw) # 适用于整个body是JSON字符串的情况
except json.JSONDecodeError:
pass # 不是合法JSON,走表单分支
更稳妥的是把JSON放在特定表单字段里(比如json_payload),再单独取:
- 前端提交:
FormData.append('json_payload', JSON.stringify({user_id: 123})) - 后端获取:
json_str = request.form.get('json_payload'),然后json.loads(json_str) - 务必校验
json_str非空且是字符串类型,避免None传给json.loads抛错
混合数据(文件+JSON字段)的正确接收姿势
这是最常踩坑的场景:上传文件的同时还要传结构化元数据。不能把JSON塞进request.json,也不能直接json.loads(request.data)——因为request.data在multipart下为空,所有字段都归到request.form和request.files里。
- 元数据必须以字符串形式放进
request.form某字段(如metadata),前端用JSON.stringify序列化后再append - 后端用
request.form.get('metadata')取值,再json.loads()解析 - 文件用
request.files.get('file')单独处理,二者互不影响 - 别试图用
request.get_json(force=True)强行解析——它会忽略Content-Type,但对multipart体仍可能失败或返回None
为什么不用request.get_json(silent=True)兜底?
silent=True只是让get_json()失败时不抛异常,而是返回None,但它解决不了根本问题:Content-Type不匹配时,Flask压根不会去解析body内容。所以即使加了silent=True,在表单请求里依然拿不到JSON。
真正需要的是路径判断逻辑:
- 先看
request.is_json——它只检查Content-Type,不解析内容 - 再根据结果分流:
if request.is_json: data = request.get_json(),否则从request.form或request.get_data()取 - 注意
request.is_json对application/json;charset=utf-8也返回True,但对text/plain或multipart一定为False
混合数据的关键永远是「约定好传输方式」,而不是靠Flask自动猜——JSON字段就老实用表单键名传字符串,别指望框架跨Content-Type做智能合并。


















