Как да конвертирате всички десетични числа в структура от данни на 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)

за съжаление, това не конвертира десетични числа, които се намират в dict или списък.

Как мога да конвертирам всички десетични числа в структура от данни на 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 repo. - person All Workers Are Essential; 18.11.2019
comment
Не бях проверил моята версия на колбата; поради проблеми с някои изисквания за подпакети, които нямам време да сортирам в момента (вероятно поради това, че eve-sqlalchemy е много изостанал от eve), трябваше да закача eve на ‹0.8, което води до flask== 0,12. - person hlongmore; 18.11.2019