Python 到 JSON 序列化在十进制上失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16957275/
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 00:05:13  来源:igfitidea点击:

Python to JSON Serialization fails on Decimal

pythonjsondecimal

提问by Dinesh

I have a python object which includes some decimals. This is causing the json.dumps() to break.

我有一个包含一些小数的 python 对象。这导致 json.dumps() 中断。

I got the following solution from SO (e.g. Python JSON serialize a Decimal object) but the recoomended solution still does not work. Python website - has the exact same answer.

我从 SO 得到以下解决方案(例如Python JSON serialize a Decimal object),但推荐的解决方案仍然不起作用。Python 网站 - 有完全相同的答案。

Any suggestions how to make this work?

任何建议如何使这项工作?

Thanks. Below is my code. It looks like the dumps() doesn't even go into the specialized encoder.

谢谢。下面是我的代码。看起来 dumps() 甚至没有进入专门的编码器。

clayton@mserver:~/python> cat test1.py
import json, decimal

class DecimalEncoder(json.JSONEncoder):
        def _iterencode(self, o, markers=None):
                print "here we go o is a == ", type(o)
                if isinstance(o, decimal.Decimal):
                        print "woohoo! got a decimal"
                        return (str(o) for o in [o])
                return super(DecimalEncoder, self)._iterencode(o, markers)

z = json.dumps( {'x': decimal.Decimal('5.5')}, cls=DecimalEncoder )
print z
clayton@mserver:~/python> python test1.py
Traceback (most recent call last):
  File "test1.py", line 11, in <module>
    z = json.dumps( {'x': decimal.Decimal('5.5')}, cls=DecimalEncoder )
  File "/home/clayton/python/Python-2.7.3/lib/python2.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/home/clayton/python/Python-2.7.3/lib/python2.7/json/encoder.py", line 201, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/home/clayton/python/Python-2.7.3/lib/python2.7/json/encoder.py", line 264, in iterencode
    return _iterencode(o, 0)
  File "/home/clayton/python/Python-2.7.3/lib/python2.7/json/encoder.py", line 178, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: Decimal('5.5') is not JSON serializable
clayton@mserver:~/python>

采纳答案by Martijn Pieters

It is not (no longer) recommended you create a subclass; the json.dump()and json.dumps()functions take a defaultfunction:

不(不再)建议您创建子类;的json.dump()json.dumps()函数采用一个default函数:

def decimal_default(obj):
    if isinstance(obj, decimal.Decimal):
        return float(obj)
    raise TypeError

json.dumps({'x': decimal.Decimal('5.5')}, default=decimal_default)

Demo:

演示:

>>> def decimal_default(obj):
...     if isinstance(obj, decimal.Decimal):
...         return float(obj)
...     raise TypeError
... 
>>> json.dumps({'x': decimal.Decimal('5.5')}, default=decimal_default)
'{"x": 5.5}'

The code you found only worked on Python 2.6 and overrides a private method that is no longer called in later versions.

您发现的代码仅适用于 Python 2.6,并覆盖了在更高版本中不再调用的私有方法。

回答by FearlessFuture

I can't believe that no one here talked about using simplejson, which supports deserialization of Decimal out of the box.

我不敢相信这里没有人谈论使用 simplejson,它支持开箱即用的 Decimal 反序列化。

import simplejson
from decimal import Decimal

simplejson.dumps({"salary": Decimal("5000000.00")})
'{"salary": 5000000.00}'

simplejson.dumps({"salary": Decimal("1.1")+Decimal("2.2")-Decimal("3.3")})
'{"salary": 0.0}'

回答by Fran?ois Constant

If you're using Django. There is a great class for Decimal and date fields:

如果您使用的是 Django。Decimal 和 date 字段有一个很好的类:

https://docs.djangoproject.com/en/1.10/topics/serialization/#djangojsonencoder

https://docs.djangoproject.com/en/1.10/topics/serialization/#djangojsonencoder

To use it:

要使用它:

import json
from django.core.serializers.json import DjangoJSONEncoder

json.dumps(value, cls=DjangoJSONEncoder)