Подтвердить что ты не робот

Сегментация Python для JSON не выполняется на десятичной основе

У меня есть объект python, который содержит некоторые десятичные числа. Это вызывает разрыв json.dumps().

Я получил следующее решение от SO (например, Python JSON сериализует объект Decimal), но исправленное решение все еще не работает. Сайт Python - имеет тот же самый ответ.

Любые предложения, как сделать эту работу?

Спасибо. Ниже мой код. Похоже, что дампы() даже не входят в специализированный кодер.

[email protected]:~/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
[email protected]:~/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
[email protected]:~/python>
4b9b3361

Ответ 1

Нет (больше не рекомендуется) создавать подкласс; функции 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)

Демо:

>>> 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}'

Код, который вы нашли, работал только на Python 2.6 и переопределяет частный метод, который больше не вызывается в более поздних версиях.

Ответ 2

Я не могу поверить, что здесь никто не говорил об использовании 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}'