web-dev-qa-db-ja.com

Flask jsonifyオブジェクトのリスト

Jsonifyする必要があるオブジェクトのリストがあります。 flask jsonify docsを見てきましたが、まだ理解できていません。

私のクラスには複数のinst-varがあり、それぞれが文字列です: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 __== '__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
    }
  ]
}
49
Jared Nedzel

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)
_
72
Martijn Pieters

jsonモジュールのドキュメント を見ると、 サブクラスJSONEncoderを使用してdefaultメソッドをオーバーライドし 、そこでタイプのサポートを追加します。オブジェクトを含む可能性のある複数の異なる構造をシリアル化する場合、これが最も一般的な処理方法になります。

jsonifyを使用する場合は、事前にオブジェクトを単純な型に変換する方が簡単です(たとえば、Martijnが提案するように、クラスで独自のメソッドを定義することにより)。

3
Amber