Flask在gunicorn生产环境JSON返回图片和Decimal类型序列化报错如何解决
问题根源
base64.b64encode()返回值为bytes类型,JSON本身不支持字节类型序列化,你当前代码用str(avatar)转换会得到带b'前缀的特殊字符串格式,生产环境严格的JSON校验会直接报错,开发环境的宽松校验/低版本 Flask 兼容逻辑导致没有触发异常- Python 标准
json模块默认不支持Decimal类型的序列化,所以会抛出同类型错误
解决方案
方案1:针对性快速修复
针对报错类型单独处理字段:
- 修正
get_user_image的返回值,将base64字节流转为纯字符串:
def get_user_image(usr_rec): with open("config.json",) as config: data = json.load(config) avatar = data["PATHS"]["AVATAR"] file_ext = os.path.splitext(usrdata["avatar"])[1] if usrdata["avatar"] else ".png" file_fmt = ".jpeg" if file_ext.upper()== ".JPG" else file_ext path = "{}/{}{}".format(avatar,usr_rec["recordid"],file_ext) img = Image.open(path,mode="r") barr = io.BytesIO() img.save(barr,format="{}".format(file_fmt[1:].upper())) # 新增decode转utf-8纯字符串 return b64encode(barr.getvalue()).decode('utf-8')
- Decimal字段在返回前手动转成
float或者str类型即可,转str不会丢失数值精度
方案2:全局自定义JSON编码器(更推荐,一次性解决所有序列化问题)
给Flask app自定义JSON编码器,统一处理bytes、Decimal等特殊类型,后续不需要单独处理每个字段:
from flask import Flask, json from decimal import Decimal class CustomJSONEncoder(json.JSONEncoder): def default(self, o): # 统一处理bytes类型(包括base64编码结果) if isinstance(o, bytes): return o.decode('utf-8') # 统一处理Decimal类型 if isinstance(o, Decimal): # 可按需转float或者str,转str不会丢失精度 return float(o) # 其他类型走默认序列化逻辑 return super().default(o) app = Flask(__name__) # 替换Flask默认的JSON编码器 app.json_encoder = CustomJSONEncoder
配置完成后原有业务代码不需要修改,生产环境即可正常完成JSON序列化。
内容的提问来源于stack exchange,提问作者Elcid_91
相关产品推荐
相关产品推荐

