python url_for用法 - Flask jsonify對象列表




ajax教學 manual (3)

如果你看一下json模塊的文檔 ,它會提到你可以JSONEncoder來覆蓋它的default方法並在那裡添加對類型的支持。 如果您要序列化可能包含對象的多個不同結構,那麼這將是處理它的最通用方法。

如果你想使用jsonify ,可能更容易提前將對象轉換為簡單類型(例如,通過在類上定義自己的方法,如Martijn所建議的那樣)。

我有一個需要jsonify的對象列表。 我看過燒瓶jsonify文檔,但我只是沒有得到它。

我的班級有幾個inst-vars,每個都是一個字符串: gene_idgene_symbolp_value 。 我需要做些什麼才能將其序列化為JSON?

我天真的代碼:

jsonify(eqtls = my_list_of_eqtls)

結果是:

TypeError: <__main__.EqtlByGene object at 0x1073ff790> is not JSON serializable

據推測,我必須告訴jsonify如何序列化EqtlByGene ,但我找不到一個顯示如何序列化類實例的示例。

這段代碼現在有效(非常感謝Martijn Pieters!):

class EqtlByGene(Resource):

    def __init__(self, gene_id, gene_symbol, p_value):
        self.gene_id = gene_id
        self.gene_symbol = gene_symbol
        self.p_value = p_value

class EqtlJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, EqtlByGene):
            return {
                   'gene_id'     : obj.gene_id,
                   'gene_symbol' : obj.gene_symbol,
                   'p_value'     : obj.p_value
            }
        return super(EqtlJSONEncoder, self).default(obj)

class EqtlByGeneList(Resource):
    def get(self):
        eqtl1 = EqtlByGene(1, 'EGFR', 0.1)
        eqtl2 = EqtlByGene(2, 'PTEN', 0.2)
        eqtls = [eqtl1, eqtl2]
        return jsonify(eqtls_by_gene = eqtls)

api.add_resource(EqtlByGeneList, '/eqtl/eqtlsbygene')
app.json_encoder = EqtlJSONEncoder
if __name__ == '__main__':
    app.run(debug=True)

當我通過curl調用它時,我得到:

{
  "eqtls_by_gene": [
    {
      "gene_id": 1, 
      "gene_symbol": "EGFR", 
      "p_value": 0.1
    }, 
    {
      "gene_id": 2, 
      "gene_symbol": "PTEN", 
      "p_value": 0.2
    }
  ]
}

為您的EqltByGene一個返回字典的額外方法:

class EqltByGene(object):
    #

    def serialize(self):
        return {
            'gene_id': self.gene_id, 
            'gene_symbol': self.gene_symbol,
            'p_value': self.p_value,
        }

然後使用列表推導將對象列表轉換為可序列化值列表:

jsonify(eqtls=[e.serialize() for e in my_list_of_eqtls])

另一種方法是為json.dumps()函數編寫一個鉤子函數,但由於你的結構相當簡單,列表理解和自定義方法方法更簡單。

你也可以真正冒險並flask.json.JSONEncoder ; 給它一個default()方法,將你的EqltByGene()實例轉換為可序列化的值:

from flask.json import JSONEncoder

class MyJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, EqltByGene):
            return {
                'gene_id': obj.gene_id, 
                'gene_symbol': obj.gene_symbol,
                'p_value': obj.p_value,
            }
        return super(MyJSONEncoder, self).default(obj)

並將其分配給app.json_encoder屬性

app = Flask(__name__)
app.json_encoder = MyJSONEncoder

並直接將您的列表傳遞給jsonify()

return jsonify(my_list_of_eqtls)

小心使用isinstance

isinstance(True, bool)
True
>>> isinstance(True, int)
True

但是鍵入

type(True) == bool
True
>>> type(True) == int
False




python json serialization flask