我在基于 FastAPI 的应用程序中使用基于 Pydantic 的响应模型和 Decimal。我想返回精度高达 20 位小数的响应。但序列化后,将15位小数四舍五入为14位。
例如:
Original Decimal : 328.448267489936666
Decimal in Response : 328.44826748993665
我尝试过设置
getcontext.prec = 15
,但没有效果。
最小可重复示例:
from decimal import getcontent, Decimal
from fastapi import FastAPI
from typing import Dict
app = FastAPI()
@app.get("/")
def read_root()->Dict[str, Decimal]:
getcontext().prec = 15
return {"a": Decimal(328.448267489936666)}
依赖关系: fastapi==0.92.0
uvicorn==0.20.0
pydantic==1.10.5
Python 3.7
使用
Decimal(328.448267489936666)
会发生一些精度损失,因为您要将浮点数转换为小数 - 使用 Decimal("328.448267489936666")
将字符串转换为小数,这样您就可以得到精确的 Decimal
,然后:
import decimal
from fastapi import FastAPI
from typing import Dict
app = FastAPI()
@app.get("/")
def read_root() -> Dict[str, decimal.Decimal]:
decimal.getcontext().prec = 15
return {"a": decimal.Decimal("328.448267489936666")}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, port=11111)
~ $ curl http://localhost:11111
{"a":"328.448267489936666"}
注意 Decimal 在 JSON 中是如何成为字符串的;这是因为许多 JSON 解码器仅使用浮点数来表示数字内容(至少默认情况下如此),并且也不能相信它是精确的。