Попробуй это.Вы должны добавить некоторые специальные регистры для диктовок, списков, наборов и т. Д., Но, ссылаясь на абстрактные базовые классы из collections.abc
, вы избегаете явного тестирования на конкретные типы.
Обратите внимание, что тест для Sequence
должен избегать сопоставления для типов str
, поскольку итерация по str
дает набор из 1 символа str
s, которые также могут повторяться Sequence
s и так далее, пока не достигнете предела рекурсии.Я не смог найти ABC, который представляет «контейнер последовательности, но не str».
(Я также должен повторить критику Алекса Мартелли из соответствующего поста о том, что нужно проделать такую большую работу только для форматированияопределенный тип говорит о проблемах в дизайне классов в этом модуле.)
import json
from collections.abc import Mapping, Sequence
a = 0.001234567
class ScientificNotationEncoder(json.JSONEncoder):
def iterencode(self, o, _one_shot=False):
if isinstance(o, float):
return "{:e}".format(o)
elif isinstance(o, Mapping):
return "{{{}}}".format(', '.join('"{}" : {}'.format(str(ok), self.iterencode(ov))
for ok, ov in o.items()))
elif isinstance(o, Sequence) and not isinstance(o, str):
return "[{}]".format(', '.join(map(self.iterencode, o)))
return ', '.join(super().iterencode(o, _one_shot))
aout = json.dumps([a, a, "xyzzy", 42, {'z': a}, (a, a, a),],
cls=ScientificNotationEncoder)
print(aout)
# loading back in seems to still work okay!
print(json.loads(aout))
Отпечатки:
[1.234567e-03, 1.234567e-03, "xyzzy", 42, {"z" : 1.234567e-03}, [1.234567e-03, 1.234567e-03, 1.234567e-03]]
[0.001234567, 0.001234567, 'xyzzy', 42, {'z': 0.001234567}, [0.001234567, 0.001234567, 0.001234567]]