Flask jsonify对象列表

时间:2014-01-28 16:38:38

标签: python json serialization flask

我有一个需要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
    }
  ]
}

2 个答案:

答案 0 :(得分:67)

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 attribute

app = Flask(__name__)
app.json_encoder = MyJSONEncoder

然后直接将您的列表传递给jsonify()

return jsonify(my_list_of_eqtls)

答案 1 :(得分:3)

如果您查看the docs for the json module,则会提到您可以subclass JSONEncoder to override its default method并在那里添加对类型的支持。如果您要序列化可能包含对象的多个不同结构,那么这将是处理它的最通用方法。

如果您想使用jsonify,可能更容易提前将对象转换为简单类型(例如,通过在类上定义您自己的方法,如Martijn所建议的那样)。

相关问题