Python JSON: TypeError: Decimal('34.3') 不是 JSON 可序列化的

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31202956/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 09:38:17  来源:igfitidea点击:

JSON: TypeError: Decimal('34.3') is not JSON serializable

pythonjson

提问by Tauseef Hussain

I am running an SQL query which returns a list of Decimals. When I try to convert this into JSON i get the type error.

我正在运行一个 SQL 查询,它返回一个小数列表。当我尝试将其转换为 JSON 时,出现类型错误。

The query:

查询:

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 """)

Result List:

结果列表:

[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')]

Code:

代码:

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

list = json.dumps(testlist)

And the I get the Unable to serialize errorTried looking up online, no much help. Please note that the final list would go as input data to a chart.

我得到了Unable to serialize error尝试在线查找,没有太大帮助。请注意,最终列表将作为图表的输入数据。

采纳答案by metatoaster

As the error says, the Decimaltype is not able to be serialized directly into JSON. Considering casting the Decimalinto a floatif you wish to keep that as a number, however you may get rounding errors. i.e.

正如错误所说,该Decimal类型无法直接序列化为 JSON。如果您希望将其保留为数字,请考虑将其Decimal转换float为 a,但是您可能会遇到舍入错误。IE

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

Or alternatively build the list using list comprehension, this time I cast to str.

或者,或者使用列表理解构建列表,这次我转换为str.

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

The latter is an appropriate representation as the Decimaltype can be unambiguously represented by str. You can grab the original value like so

后者是一种适当的表示,因为该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_dlistshould be identical to the original templist.

new_dlist应该和原来的一样templist

回答by LittleQ

Use a override default:

使用覆盖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)

Or just do stron Decimalobject:

或者只是strDecimal对象上做:

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