Flask jsonify a list of objects
flask, json, python, serialization
Solution
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.
Problem
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") ```