[英]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_id
、 gene_symbol
、 p_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.