Python接口返回中文乱码主因是响应头未显式声明charset=utf-8,Flask需手动设置content_type、Django需传content_type参数、FastAPI自定义响应时易遗漏charset声明,前端还需清缓存验证。

Python接口返回中文乱码,90% 是因为响应头没显式声明 charset=utf-8,浏览器或客户端按 ISO-8859-1 解析 UTF-8 字节流导致的。
Flask 返回 JSON 时 Content-Type 缺少 charset
Flask 的 jsonify() 和 Response 默认不往 Content-Type 头里写 charset=utf-8,即使你设了 response.charset = 'utf-8',最终 header 仍是 application/json,不含分号后的声明。
正确做法是手动拼接:
from flask import Response
import json
data = json.dumps({"msg": "你好"}, ensure_ascii=False)
return Response(data, content_type='application/json; charset=utf-8')
或者用 make_response 后改 headers:
立即学习“Python免费学习笔记(深入)”;
resp = make_response(json.dumps(...))resp.headers['Content-Type'] = 'application/json; charset=utf-8'
全局补全可用 after_request 钩子,但注意别覆盖已有 charset(比如文件下载接口返回 application/octet-stream)。
Django JsonResponse 默认不带 charset 参数
Django 的 JsonResponse 默认 header 是 application/json,虽内部用 UTF-8 编码 body,但缺声明会导致旧版 Android WebView 或 Java 客户端误判为 ISO-8859-1。
必须显式传 content_type 字符串:
from django.http import JsonResponse
return JsonResponse({"msg": "你好"}, content_type='application/json; charset=utf-8')
如果用 HttpResponse 手动序列化,json.dumps(..., ensure_ascii=False) 不够,content_type 参数不能省。
注意:Django 4.2+ 对 JsonResponse 的 charset 关键字参数支持有限,仍靠 content_type 字符串控制。
FastAPI 自定义响应容易漏 charset 声明
JSONResponse 默认带 application/json; charset=utf-8,这点比 Flask/Django 友好;但一旦你用 Response 包原始字符串、返回 PlainTextResponse、或用 StreamingResponse,就完全不带 charset 声明。
常见错误写法:
-
return "你好"→ 返回text/plain,无 charset -
return Response("你好", media_type="text/plain")→ 缺; charset=utf-8
正确写法:
from fastapi import FastAPI
from fastapi.responses import PlainTextResponse
app = FastAPI()
@app.get("/")
def read_root():
return PlainTextResponse("你好", media_type="text/plain; charset=utf-8")
最易被忽略的是:前端未设 responseType 时,fetch 或 XMLHttpRequest 可能缓存错误解析结果,导致改后端也看不到效果——务必清缓存或加时间戳参数验证。


















