11

json.dumps outputs small float or decimal values using scientific notation, which is unacceptable to the json-rpc application this output is sent to.

>>> import json
>>> json.dumps({"x": 0.0000001})
'{"x": 1e-07}'

I want this output instead:

'{"x": 0.0000001}'

It would be ideal to avoid introducing additional dependencies.

4

4 に答える 4

6

フォーマットの 1 つの方法

evil = {"x": 0.00000000001}

Decimalの「f」フォーマッタを盗むことです。これは、クロッピングの問題と指数の両方を回避できる唯一の簡単な方法ですが、スペース効率が良くありません

class FancyFloat(float):
    def __repr__(self):
        return format(Decimal(self), "f")

それを使用するには、入力を「10 進数化」するエンコーダを作成できます。

class JsonRpcEncoder(json.JSONEncoder):
    def decimalize(self, val):
        if isinstance(val, dict):
            return {k:self.decimalize(v) for k,v in val.items()}

        if isinstance(val, (list, tuple)):
            return type(val)(self.decimalize(v) for v in val)

        if isinstance(val, float):
            return FancyFloat(val)

        return val

    def encode(self, val):
        return super().encode(self.decimalize(val))

JsonRpcEncoder().encode(evil)
#>>> '{"x": 0.00000000000999999999999999939496969281939810930172340963650867706746794283390045166015625}'

または、もちろん、10 進数化を関数に移動して、それを前に呼び出すこともできますjson.dumps

たとえそれが不自由な方法であっても、それは私がそれを行う方法です。

于 2013-09-21T19:57:00.533 に答える
0

これは補足的な解説であり、科学的表記法を回避するための完全な回答ではありませんjson.dumps。解析の余分なラウンドで、parse_floatオプション onjson.loadsはいくつかのことを助けることができます。

$ python
Python 3.7.10 | packaged by conda-forge | (default, Feb 19 2021, 16:07:37) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import json
>>> data = {"x": 0.0000001}
>>> json.dumps(data)
'{"x": 1e-07}'
>>> data = json.loads(json.dumps(data), parse_float=lambda x: round(float(x), 6))
>>> json.dumps(data)
'{"x": 0.0}'

これは、ゼロに丸められる小さな値の科学的表記法を回避するだけです。これは大規模なデータセットでは効率的ではありませんが、一部のユースケースでは役立ちます。これは、科学表記法を完全に回避するものではありません。

>>> data = {"x": 0.00001}
>>> data = json.loads(json.dumps(data), parse_float=lambda x: round(float(x), 6))
>>> json.dumps(data)
'{"x": 1e-05}'
于 2021-03-23T16:59:10.627 に答える