Python 3.x 无法将 Decimal() 序列化为 JSON
Posted
技术标签:
【中文标题】Python 3.x 无法将 Decimal() 序列化为 JSON【英文标题】:Python 3.x cannot serialize Decimal() to JSON 【发布时间】:2017-09-26 11:57:12 【问题描述】:我之前问过这个问题,它被标记为与this 重复,但是接受的答案不起作用,甚至 pylint 显示代码中有错误。
我想做什么:
from decimal import Decimal
import json
thang =
'Items': ['contact_id': Decimal('2'), 'street_name': 'Asdasd', 'contact_id': Decimal('1'), 'name': 'Lukas', 'customer_id': Decimal('1')],
'Count': 2
print(json.dumps(thang))
这会引发:
TypeError: Object of type 'Decimal' is not JSON serializable
所以我尝试了链接的answer:
from decimal import Decimal
import json
thang =
'Items': ['contact_id': Decimal('2'), 'street_name': 'Asdasd', 'contact_id': Decimal('1'), 'name': 'Lukas', 'customer_id': Decimal('1')],
'Count': 2
class DecimalEncoder(json.JSONEncoder):
def _iterencode(self, o, markers=None):
if isinstance(o, Decimal):
# wanted a simple yield str(o) in the next line,
# but that would mean a yield on the line with super(...),
# which wouldn't work (see my comment below), so...
return (str(o) for o in [o])
return super(DecimalEncoder, self)._iterencode(o, markers)
print(json.dumps(thang, cls=DecimalEncoder))
这里 linter 显示 return super(DecimalEncoder, self)._iterencode(o, markers)
行有错误,因为 Super of 'DecimalEncoder' has no '_iterencode' member
和运行时抛出
TypeError: Object of type 'Decimal' is not JSON serializable
我该如何进行这项工作?
【问题讨论】:
【参考方案1】:我想序列化 Decimal 为 JSON,并将其反序列化返回到其他地方字典中的实际 Decimal 类对象。
这是适用于我的示例程序(Python 3.6):
import json
from decimal import Decimal
import decimal
class DecimalEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, decimal.Decimal):
return '__Decimal__': str(obj)
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, obj)
def as_Decimal(dct):
if '__Decimal__' in dct:
return decimal.Decimal(dct['__Decimal__'])
return dct
sample_dict =
"sample1": Decimal("100"),
"sample2": [ Decimal("2.0"), Decimal("2.1") ],
"sample3": Decimal("3.1415"),
"other": "hello!"
print("1. sample_dict is:\n0\n".format(sample_dict))
sample_dict_encoded_as_json_string = json.dumps(sample_dict, cls=DecimalEncoder)
print("2. sample_dict_encoded_as_json_string is:\n0\n".format(sample_dict_encoded_as_json_string))
sample_dict_recreated = json.loads(sample_dict_encoded_as_json_string, object_hook=as_Decimal)
print("3. sample_dict_recreated is:\n0\n".format(sample_dict_recreated))
这是输出:
1. sample_dict is:
'sample1': Decimal('100'), 'sample2': [Decimal('2.0'), Decimal('2.1')], 'sample3': Decimal('3.1415'), 'other': 'hello!'
2. sample_dict_encoded_as_json_string is:
"sample1": "__Decimal__": "100", "sample2": ["__Decimal__": "2.0", "__Decimal__": "2.1"], "sample3": "__Decimal__": "3.1415", "other": "hello!"
3. sample_dict_recreated is:
'sample1': Decimal('100'), 'sample2': [Decimal('2.0'), Decimal('2.1')], 'sample3': Decimal('3.1415'), 'other': 'hello!'
希望这会有所帮助!
【讨论】:
【参考方案2】:结果证明该答案已过时,并且有另一个 answer 具有有效的解决方案:
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return str(o)
return super(DecimalEncoder, self).default(o)
请注意,这会将十进制转换为其字符串表示形式(例如,"1.2300"
)为 a。不丢失有效数字和 b。防止舍入错误。
【讨论】:
这完全违背了decimal.Decimal
类的目的。它应该序列化为字符串而不是浮点数,因为浮点数不准确。
完全同意。将 Decimal 序列化为浮点数的答案不应该是最佳答案,因为它非常不准确。例如,您最终可能会因为浮点舍入错误而违反法律合同。以上是关于Python 3.x 无法将 Decimal() 序列化为 JSON的主要内容,如果未能解决你的问题,请参考以下文章
python查询mysql数据库,执行sql后查询结果数据类型为Decimal,解决方法
无法将类型为“System.Decimal”的对象强制转换为类型“System.Char[]”。
C#中decimal.Parse(t70OnlinePrice.Value)保留两位小数
如何将 Python Decimal 实例转换为 C++ double?