JSON:类型错误:Decimal('34.3')无法序列化为JSON。

12

我正在运行一个SQL查询,它返回一个十进制数的列表。当我尝试将其转换为JSON时,我遇到了类型错误。

查询:

res = db.execute("""
SELECT CAST ((SUM(r.SalesVolume)/1000.0) AS decimal(6,1))
FROM RawData r
INNER JOIN Product p
ON r.ProductId = p.ProductId 
INNER JOIN Calendar c
ON r.DayId = c.DayId
WHERE c.WeekCodeInYear BETWEEN 1 AND 12
AND 
c.YearId = 2014
GROUP BY c.WeekCodeInYear """)

结果列表:

[Decimal('34.3'), Decimal('50.9'), Decimal('31.5'), Decimal('23.3'), Decimal('19
.7'), Decimal('56.9'), Decimal('43.8'), Decimal('35.2'), Decimal('29.2'), Decima
l('43.7'), Decimal('42.6'), Decimal('23.4')]

代码:

for row in res:
    testlist.append (row[0])
    print testlist

list = json.dumps(testlist)

然后我收到了无法序列化错误。尝试在网上查找,但没有太多帮助。请注意,最终列表将作为输入数据传递给图表。


“Decimal对象”不可JSON序列化。请展示执行结果的“print testlist”。 - LittleQ
@LittleQ 上面的结果列表是执行 testlist 的结果。 - Tauseef Hussain
我明白你的意思。顺便说一句,list是一个内置类型,最好不要用它作为变量名。 - LittleQ
2个回答

22

使用覆盖 default

import json
from decimal import Decimal

def default(obj):
    if isinstance(obj, Decimal):
        return str(obj)
    raise TypeError("Object of type '%s' is not JSON serializable" % type(obj).__name__)

json.dumps(testlist, default=default)

你可以直接在 Decimal 对象上使用 str 方法:

for row in res:
    testlist.append (str(row[0]))
json.dumps(testlist)

1
后者更简单。 - LittleQ
我发现扩展默认类型有点棘手,但我找到了一个人编写的库以更有组织的方式实现了更多类型的扩展。https://pypi.org/project/json-default/ 另外,我想将我的存储为浮点数,所以我将您的第6行更改为float(obj) - phyatt
同样地,在顶部的链接示例中,SimpleJson 很好地支持了 Decimal。https://github.com/simplejson/simplejson - phyatt

10

正如错误所述,Decimal类型无法直接序列化为JSON。 如果您希望将其保留为数字,请考虑将Decimal转换为float,但可能会出现舍入误差。 例如:

for row in res:
    testlist.append(float(row[0]))

或者您可以使用列表推导式来构建列表,这次我将其转换为str类型。

testlist = [str(row[0]) for row in res]

后者是一种适当的表达方式,因为Decimal类型可以通过str无歧义地表示。你可以像这样获取原始值。
from decimal import Decimal
jlist = json.dumps(testlist)  # don't use list as it's predefined type
new_list = json.loads(jlist)
new_dlist = [Decimal(s) for s in new_list]

new_dlist 应该与原始的 templist 相同。


您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - metatoaster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接