Für diejenigen, die keine Bibliothek eines Drittanbieters verwenden möchten ... Ein Problem mit der Antwort von Elias Zamaria ist, dass sie in Float konvertiert wird, was zu Problemen führen kann. Beispielsweise:
>>> json.dumps({'x': Decimal('0.0000001')}, cls=DecimalEncoder)
'{"x": 1e-07}'
>>> json.dumps({'x': Decimal('100000000000.01734')}, cls=DecimalEncoder)
'{"x": 100000000000.01733}'
Mit dieser JSONEncoder.encode()
Methode können Sie den wörtlichen json-Inhalt zurückgeben, im Gegensatz dazu JSONEncoder.default()
, dass Sie einen json-kompatiblen Typ (wie float) zurückgeben, der dann auf normale Weise codiert wird. Das Problem dabei encode()
ist, dass es (normalerweise) nur auf der obersten Ebene funktioniert. Aber es ist immer noch verwendbar, mit ein wenig zusätzlicher Arbeit (Python 3.x):
import json
from collections.abc import Mapping, Iterable
from decimal import Decimal
class DecimalEncoder(json.JSONEncoder):
def encode(self, obj):
if isinstance(obj, Mapping):
return '{' + ', '.join(f'{self.encode(k)}: {self.encode(v)}' for (k, v) in obj.items()) + '}'
if isinstance(obj, Iterable) and (not isinstance(obj, str)):
return '[' + ', '.join(map(self.encode, obj)) + ']'
if isinstance(obj, Decimal):
return f'{obj.normalize():f}' # using normalize() gets rid of trailing 0s, using ':f' prevents scientific notation
return super().encode(obj)
Welches gibt Ihnen:
>>> json.dumps({'x': Decimal('0.0000001')}, cls=DecimalEncoder)
'{"x": 0.0000001}'
>>> json.dumps({'x': Decimal('100000000000.01734')}, cls=DecimalEncoder)
'{"x": 100000000000.01734}'