
本文详解 FastAPI 中因直接传递 bytes 或非 JSON 可序列化对象(如 PIL.Image、bytes)导致的 “Object not JSON serializable” 错误,并提供基于 UploadFile 的标准文件上传方案及最佳实践。
本文详解 fastapi 中因直接传递 `bytes` 或非 json 可序列化对象(如 pil.image、bytes)导致的 “object not json serializable” 错误,并提供基于 `uploadfile` 的标准文件上传方案及最佳实践。
在 FastAPI 中,HTTP 请求体(json= 参数)必须是纯 Python 基本类型(dict、list、str、int、float、bool、None),而 bytes、PIL.Image.Image、io.BytesIO 等对象无法被 JSON 直接序列化——这正是你遇到 TypeError: Object of type bytes is not JSON serializable 的根本原因。
你的客户端代码试图将图像字节(img_bytes)作为 JSON 字段发送:
payload = {
"input_image": img_bytes, # ❌ bytes 不可 JSON 序列化
...
}
response = requests.post(url, json=payload) # ⚠️ json= 要求所有值可 JSON 化
而 FastAPI 的 @app.get() 路由也不支持接收 json 数据体(GET 请求无请求体),更无法解析原始 bytes 参数。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
✅ 正确做法:使用 UploadFile 实现文件上传,并配合 Form 或 File 依赖项。
✅ 正确的 FastAPI 接口定义(推荐)
from fastapi import FastAPI, File, UploadFile, Form, HTTPException
from typing import List
import io
from PIL import Image
app = FastAPI()
@app.post("/tripo-api")
async def generator(
input_image: UploadFile = File(..., description="输入图像文件(JPEG/PNG)"),
do_remove_background: bool = Form(...),
foreground_ratio: float = Form(...),
mc_resolution: int = Form(...),
formats: List[str] = Form(["obj", "glb"]),
):
# 验证文件类型
if not input_image.content_type.startswith("image/"):
raise HTTPException(400, "仅支持图像文件")
# 读取并转换为 PIL.Image
try:
image_bytes = await input_image.read()
pil_image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
except Exception as e:
raise HTTPException(400, f"图像解析失败: {str(e)}")
# 调用预处理与生成逻辑
output_prepr = preprocess(input_image=pil_image,
do_remove_background=do_remove_background,
foreground_ratio=foreground_ratio)
rv = generate(output_prepr, mc_resolution=mc_resolution, formats=formats)
# ⚠️ 注意:rv 必须是 JSON 可序列化的结构(如 dict/list)
# 若 generate 返回的是二进制文件(如 .obj/.glb 字节流),需转为 base64 或返回下载链接
# 示例:若 rv 是 {"obj": b'...', "glb": b'...'},请改写为:
# return {
# "obj_base64": base64.b64encode(rv["obj"]).decode(),
# "glb_base64": base64.b64encode(rv["glb"]).decode(),
# "formats": formats
# }
return {"status": "success", "result": str(rv)} # 替换为实际可序列化结果
✅ 客户端调用方式(对应上述 POST 接口)
import requests
from pathlib import Path
url = "http://localhost:8000/tripo-api"
with open("examples/captured.jpeg", "rb") as f:
files = {"input_image": ("captured.jpeg", f, "image/jpeg")}
data = {
"do_remove_background": "true", # 字符串布尔值(FastAPI 自动转换)
"foreground_ratio": "0.8",
"mc_resolution": "512",
"formats": ["obj", "glb"]
}
response = requests.post(url, files=files, data=data)
if response.status_code == 200:
print("✅ 成功:", response.json())
else:
print("❌ 失败:", response.status_code, response.text)
⚠️ 关键注意事项
- 不要在 json= 中传文件或 bytes:始终用 files= 发送二进制文件。
- GET 不适合传文件:改用 POST + UploadFile。
- 确保 generate() 返回值可 JSON 序列化:若返回模型文件字节,应编码为 base64 字符串,或存储至对象存储(如 AWS S3)后返回 URL。
- 添加异常处理与 MIME 类型校验:提升鲁棒性。
- 生产环境建议增加文件大小限制(如 max_upload_size=10 * 1024 * 1024)。
遵循以上规范,即可彻底规避 JSON 序列化错误,并构建健壮、符合 REST 标准的 3D 模型生成 API。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










