[英]Python 3.x cannot serialize Decimal() to JSON
I asked this question earlier, and it was marked as duplicate of this , but the accepted answer does not work and even pylint shows that there are errors in the code.我之前问过这个问题,它被标记为this 的重复,但接受的答案不起作用,甚至 pylint 显示代码中有错误。
What I want to do:我想做的事:
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))
This throws: TypeError: Object of type 'Decimal' is not JSON serializable
这会抛出:
TypeError: Object of type 'Decimal' is not JSON serializable
So I tried the linked 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))
And here the linter shows that line return super(DecimalEncoder, self)._iterencode(o, markers)
has errors, because Super of 'DecimalEncoder' has no '_iterencode' member
and when ran throws TypeError: Object of type 'Decimal' is not JSON serializable
这里 linter 显示 line
return super(DecimalEncoder, self)._iterencode(o, markers)
有错误,因为Super of 'DecimalEncoder' has no '_iterencode' member
并且在运行时抛出TypeError: Object of type 'Decimal' is not JSON serializable
How do I make this work?我如何使这项工作?
That answer turned out to be outdated and there was another answer with the working solution:结果证明该答案已过时,工作解决方案还有另一个答案:
class DecimalEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o, decimal.Decimal):
return str(o)
return super(DecimalEncoder, self).default(o)
Note that this will convert the decimal to its string representation (eg; "1.2300"
) to a.请注意,这会将十进制数转换为其字符串表示形式(例如;
"1.2300"
)到 a。 not lose significant digits and b.不会丢失有效数字和 b. prevent rounding errors.
防止舍入错误。
I wanted to serialize Decimal to JSON, and also deserialize it back to actual Decimal class objects in a dictionary elsewhere.我想将 Decimal序列化为JSON,并将其反序列化回其他地方字典中的实际 Decimal 类对象。
Here is my sample program which works for me (Python 3.6):这是我的示例程序(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:\n{0}\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:\n{0}\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:\n{0}\n".format(sample_dict_recreated))
And here is the output:这是输出:
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!'}
Hope this helps!希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.