1. ホーム
  2. python

[解決済み] 標準のjsonモジュールでfloatをフォーマットする

2022-05-15 13:48:21

質問

私は、標準の json モジュール を使って浮動小数点数のリストをシリアライズしています。しかし、私はこのような結果を得ています。

>>> import json
>>> json.dumps([23.67, 23.97, 23.87])
'[23.670000000000002, 23.969999999999999, 23.870000000000001]'

小数点以下2桁の浮動小数点数で表示させたい。出力はこのようになるはずです。

>>> json.dumps([23.67, 23.97, 23.87])
'[23.67, 23.97, 23.87]'

JSON Encoderクラスを独自に定義してみました。

class MyEncoder(json.JSONEncoder):
    def encode(self, obj):
        if isinstance(obj, float):
            return format(obj, '.2f')
        return json.JSONEncoder.encode(self, obj)

これは単独のfloatオブジェクトに対して動作します。

>>> json.dumps(23.67, cls=MyEncoder)
'23.67'

しかし、ネストされたオブジェクトに対しては失敗します。

>>> json.dumps([23.67, 23.97, 23.87])
'[23.670000000000002, 23.969999999999999, 23.870000000000001]'

外部依存が嫌なので、標準のjsonモジュールにこだわりたい。

どうすれば実現できますか?

どのように解決するのですか?

注意してください。 これは ではない は最近のどのバージョンのPythonでも動作します。

残念ながら、モンキーパッチによってこれを行う必要があると思います(私の意見では、これは標準ライブラリの設計上の欠陥を示すものです。 json パッケージの設計上の欠陥を示すものだと私は考えています)。例えば、このようなコードです。

import json
from json import encoder
encoder.FLOAT_REPR = lambda o: format(o, '.2f')
    
print(json.dumps(23.67))
print(json.dumps([23.67, 23.97, 23.87]))

が出る。

23.67
[23.67, 23.97, 23.87]

を望むようにします。明らかに FLOAT_REPR をオーバーライドして、float のすべての表現を制御できるようにするアーキテクチャが必要です。 json パッケージが設計された方法ではないのです:-)