Pour ceux qui ne veulent pas utiliser une bibliothèque tierce ... Un problème avec la réponse d'Elias Zamaria est qu'elle se transforme en float, ce qui peut entraîner des problèmes. Par exemple:
>>> json.dumps({'x': Decimal('0.0000001')}, cls=DecimalEncoder)
'{"x": 1e-07}'
>>> json.dumps({'x': Decimal('100000000000.01734')}, cls=DecimalEncoder)
'{"x": 100000000000.01733}'
La JSONEncoder.encode()
méthode vous permet de retourner le contenu json littéral, contrairement à JSONEncoder.default()
ce qui vous oblige à retourner un type compatible json (comme float) qui est ensuite encodé de la manière normale. Le problème encode()
est qu'il ne fonctionne (normalement) qu'au niveau supérieur. Mais c'est toujours utilisable, avec un peu de travail supplémentaire (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)
Ce qui vous donne:
>>> json.dumps({'x': Decimal('0.0000001')}, cls=DecimalEncoder)
'{"x": 0.0000001}'
>>> json.dumps({'x': Decimal('100000000000.01734')}, cls=DecimalEncoder)
'{"x": 100000000000.01734}'