Flask-SQLAlchemy查询返回Decimal对象无法直接jsonify的标准转换方法
解决Flask-SQLAlchemy查询Decimal结果无法jsonify的标准方法
我懂你碰到的这个问题——用聚合查询拿到的Decimal类型结果没法直接被Flask的jsonify序列化,虽然手动转int()能解决,但确实有更标准的处理方式,下面给你列几种常用方案:
1. 查询时直接转换类型(推荐单次场景)
在SQLAlchemy的查询语句里,用cast()函数把聚合结果直接转成Integer类型,这样查询返回的就是原生int,不用后续处理:
from sqlalchemy import cast, Integer from sqlalchemy.sql import func from sqlalchemy import or_ # 修改后的查询语句 result = ReportRecord.query.filter( or_(ReportRecord.spf_result == "pass", ReportRecord.dkim_result == "pass") ).with_entities( cast(func.sum(ReportRecord.count), Integer).label('total_passed') ).first() # 用first()更合理,因为聚合查询只会返回一条结果 # 直接用结果即可 return jsonify({"total_passed": result.total_passed})
2. 自定义JSONEncoder(推荐全局复用场景)
如果你的项目里经常需要处理Decimal转JSON的情况,自定义一个全局的JSON编码器是最高效的方式,一劳永逸:
首先定义自定义编码器:
from flask.json import JSONEncoder from decimal import Decimal class DecimalJSONEncoder(JSONEncoder): def default(self, obj): # 处理Decimal类型,转成int或者float都可以,按需选择 if isinstance(obj, Decimal): return int(obj) # 其他类型交给父类处理 return super().default(obj)
然后在Flask应用中注册这个编码器:
from flask import Flask app = Flask(__name__) app.json_encoder = DecimalJSONEncoder
之后不管你查询返回的结果里有没有Decimal,直接用jsonify处理就行,它会自动帮你转换。
3. 手动处理查询结果(临时应急场景)
如果只是偶尔需要处理一次,也可以在拿到查询结果后手动转换类型,比如:
result = ReportRecord.query.filter( or_(ReportRecord.spf_result == "pass", ReportRecord.dkim_result == "pass") ).with_entities(func.sum(ReportRecord.count).label('total_passed')).first() # 处理空结果的情况,避免报错 total_passed = int(result.total_passed) if result else 0 return jsonify({"total_passed": total_passed})
这里用first()代替all()是因为聚合查询只会返回一条结果,all()会返回包含单个元组的列表,处理起来多一步,用first()更简洁。
内容的提问来源于stack exchange,提问作者Ishan Khare
相关产品推荐
相关产品推荐

