Bagi mereka yang tidak ingin menggunakan perpustakaan pihak ketiga ... Masalah dengan jawaban Elias Zamaria adalah bahwa itu dikonversi menjadi mengambang, yang dapat mengalami masalah. Sebagai contoh:
>>> json.dumps({'x': Decimal('0.0000001')}, cls=DecimalEncoder)
'{"x": 1e-07}'
>>> json.dumps({'x': Decimal('100000000000.01734')}, cls=DecimalEncoder)
'{"x": 100000000000.01733}'
The JSONEncoder.encode()
Metode memungkinkan Anda mengembalikan konten json literal, seperti JSONEncoder.default()
yang telah Anda kembali jenis kompatibel json (seperti float) yang kemudian akan dikodekan dengan cara biasa. Masalah dengan encode()
itu (biasanya) hanya bekerja di tingkat atas. Tapi itu masih bisa digunakan, dengan sedikit kerja ekstra (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)
Yang memberi Anda:
>>> json.dumps({'x': Decimal('0.0000001')}, cls=DecimalEncoder)
'{"x": 0.0000001}'
>>> json.dumps({'x': Decimal('100000000000.01734')}, cls=DecimalEncoder)
'{"x": 100000000000.01734}'