Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
386 views
in Technique[技术] by (71.8m points)

python - Flask jsonify a list of objects

I have a list of objects that I need to jsonify. I've looked at the flask jsonify docs, but I'm just not getting it.

My class has several inst-vars, each of which is a string: gene_id, gene_symbol, p_value. What do I need to do to make this serializable as 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.

I've been trying to follow some of the suggestions show below to create my own JSONEncoder subclass. 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:

TypeError(repr(o) + " is not JSON serializable")
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Give your EqltByGene an extra method that returns a dictionary:

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.

You can also be really adventurous and subclass flask.json.JSONEncoder; give it a default() method that turns your EqltByGene() instances into a serializable value:

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 the app.json_encoder attribute:

app = Flask(__name__)
app.json_encoder = MyJSONEncoder

and just pass in your list directly to 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; e.g.:

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. The same schema can be used to validate incoming JSON data and (with the appropriate extra methods), used to produce EqltByGene instances again.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...