简体   繁体   English

Flask jsonify 对象列表

[英]Flask jsonify a list of objects

I have a list of objects that I need to jsonify.我有一个需要 jsonify 的对象列表。 I've looked at the flask jsonify docs, but I'm just not getting it.我看过烧瓶 jsonify 文档,但我只是不明白。

My class has several inst-vars, each of which is a string: gene_id , gene_symbol , p_value .我的班级有几个 inst-var,每个都是一个字符串: gene_idgene_symbolp_value What do I need to do to make this serializable as JSON?我需要做什么才能将此序列化为 JSON?

My naive code:我的天真代码:

jsonify(eqtls = my_list_of_eqtls)

Results in:结果是:

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

Presumably I have to tell jsonify how to serialize an EqtlByGene , but I can't find an example that shows how to serialize an instance of a class.大概我必须告诉 jsonify 如何序列化EqtlByGene ,但我找不到显示如何序列化类实例的示例。

I've been trying to follow some of the suggestions show below to create my own JSONEncoder subclass.我一直在尝试按照下面显示的一些建议来创建我自己的 JSONEncoder 子类。 My code is now:我的代码现在是:

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)

When I try to reach it via curl, I get:当我尝试通过 curl 到达它时,我得到:

TypeError(repr(o) + " is not JSON serializable")

Give your EqltByGene an extra method that returns a dictionary:为您的EqltByGene一个返回字典的额外方法:

class EqltByGene(object):
    #

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

then use a list comprehension to turn your list of objects into a list of serializable values:然后使用列表理解将对象列表转换为可序列化值列表:

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

The alternative would be to write a hook function for the json.dumps() function, but since your structure is rather simple, the list comprehension and custom method approach is simpler.另一种方法是为json.dumps()函数编写一个钩子函数,但由于您的结构相当简单,列表理解和自定义方法方法更简单。

You can also be really adventurous and subclass flask.json.JSONEncoder ;你也可以非常喜欢冒险并flask.json.JSONEncoder give it a default() method that turns your EqltByGene() instances into a serializable value:给它一个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)

and assign this to theapp.json_encoder attribute :并将其分配给app.json_encoder属性

app = Flask(__name__)
app.json_encoder = MyJSONEncoder

and just pass in your list directly to jsonify() :并将您的列表直接传递给jsonify()

return jsonify(my_list_of_eqtls)

You could also look at the Marshmallow project for a more full-fledged and flexible project for serializing and de-serializing objects to Python primitives that easily fit JSON and other such formats;您还可以查看Marshmallow 项目以获得更成熟和灵活的项目,用于将对象序列化和反序列化为 Python 原语,可轻松适应 JSON 和其他此类格式; eg:例如:

from marshmallow import Schema, fields

class EqltByGeneSchema(Schema):
    gene_id = fields.Integer()
    gene_symbol = fields.String()
    p_value = fields.Float()

and then use然后使用

jsonify(eqlts=EqltByGeneSchema().dump(my_list_of_eqtls, many=True)

to produce JSON output.生成 JSON 输出。 The same schema can be used to validate incoming JSON data and (with the appropriate extra methods ), used to produce EqltByGene instances again.相同的模式可用于验证传入的 JSON 数据和(使用适当的额外方法),用于再次生成EqltByGene实例。

If you look at the docs for the json module , it mentions that you can subclass JSONEncoder to override its default method and add support for types there.如果您查看json模块的文档,它会提到您可以JSONEncoder以覆盖其default方法并在那里添加对类型的支持。 That would be the most generic way to handle it if you're going to be serializing multiple different structures that might contain your objects.如果您要序列化可能包含您的对象的多个不同结构,那将是最通用的处理方式。

If you want to use jsonify , it's probably easier to convert your objects to simple types ahead of time (eg by defining your own method on the class, as Martijn suggests).如果您想使用jsonify ,提前将您的对象转换为简单类型可能更容易(例如,通过在类上定义您自己的方法,正如 Martijn 建议的那样)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM