Как преобразовать все десятичные числа в структуре данных Python в строку?

Я создаю веб-сайт, используя Flask, из которого я часто использую метод jsonify для преобразования в основном словарей в Json.

Проблема в том, что я также часто использую десятичные числа, и, к сожалению, jsonify не может обрабатывать десятичные числа:

jsonify({'a': Decimal('1')})

приводит к:

=== (a long stacktrace preceding this) ===
File "/usr/local/lib/python2.7/dist-packages/flask/json.py", line 83, in default
return _json.JSONEncoder.default(self, o)
File "/usr/lib/python2.7/json/encoder.py", line 184, in default
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: Decimal('1') is not JSON serializable

Поэтому я хотел обернуть jsonify в такой метод:

def myOwnJsonify(item):
    if isinstance(item, Decimal):
        return flask.jsonify(str(item))
    else:
        return flask.jsonify(item)

к сожалению, это не преобразует десятичные числа, которые находятся в словаре или списке.

Как я могу преобразовать все десятичные числа в структуре данных python (будь то список, dict, кортеж и т. д.) в строку, чтобы я мог безопасно преобразовать структуру данных в json?


person kramer65    schedule 11.07.2014    source источник
comment
Возможно, это не лучший способ, но не могли бы вы создать подкласс Decimal и переопределить его метод __repr__, чтобы получить то, что вы хотите?   -  person Two-Bit Alchemist    schedule 12.07.2014


Ответы (1)


Вы можете переопределить кодировщик JSON приложения, установив атрибут json_encoder в вашем экземпляр приложения:

import flask

app = flask.Flask(...)
app.json_encoder = MyJSONEncoder

Затем вы можете создать подкласс JSONEncoder Flask и переопределить default() для обеспечения поддержки дополнительных типов:

import decimal
import flask.json

class MyJSONEncoder(flask.json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj, decimal.Decimal):
            # Convert decimal instances to strings.
            return str(obj)
        return super(MyJSONEncoder, self).default(obj)
person All Workers Are Essential    schedule 11.07.2014
comment
Вероятно, дело просто в разных версиях, но мне пришлось сделать app.data.json_encoder_class = MyJSONEncoder, чтобы все заработало. - person hlongmore; 18.11.2019
comment
@hlongmore Я проверил последнюю версию Flask, 1.1.1, и похоже, что она все еще использует атрибуты json_encoder/decoder в классе Flask. Я не вижу упоминания о json_encoder_class в репозитории Github. - person All Workers Are Essential; 18.11.2019
comment
Я не проверял версию фляги; из-за проблем с некоторыми требованиями к подпакетам, с которыми у меня сейчас нет времени разбираться (вероятно, из-за того, что eve-sqlalchemy сильно отстает от eve), мне пришлось закрепить eve на ‹0,8, что приводит к flask== 0,12. - person hlongmore; 18.11.2019