2014-01-28 4 views
29

У меня есть список объектов, которые мне нужны для jsonify. Я посмотрел на флягу jsonify docs, но я просто не понимаю.Flask jsonify список объектов

Мой класс имеет несколько inst-vars, каждая из которых представляет собой строку: gene_id, gene_symbol, p_value. Что мне нужно сделать, чтобы сделать сериализуемым как JSON?

Мой наивный код:

jsonify(eqtls = my_list_of_eqtls) 

Результаты в:

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

Предположительно я должен сказать jsonify как сериализовать EqtlByGene, но я не могу найти пример, который показывает, как сериализовать экземпляр класса.

Этот код теперь работает (со многими благодаря Martijn Питерс!):

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) 

Когда я называю это через завиток, я получаю:

{ 
    "eqtls_by_gene": [ 
    { 
     "gene_id": 1, 
     "gene_symbol": "EGFR", 
     "p_value": 0.1 
    }, 
    { 
     "gene_id": 2, 
     "gene_symbol": "PTEN", 
     "p_value": 0.2 
    } 
    ] 
} 
+0

JSON не может сериализовать экземпляры класса. Однако вы решили сериализовать свой класс, что сериализация не будет каноническим JSON и будет нуждаться в явной поддержке с другой стороны при десериализации вашего JSON. – lanzz

ответ

53

Дайте вашим 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) 
+0

@Martijn Питерс: Я пробовал: 'code' класс EqtlJSONEncoder (JSONEncoder): четкости по умолчанию (я, объект): если isinstance (объект, EqtlByGene): возвращение { 'gene_id': OBJ. gene_id, 'gene_symbol': obj.gene_symbol, 'p_value': obj.p_value } возвращение JSONEncoder.default (я, объект) .... app.json_encoder (EqtlJSONEncoder) 'code' Но Я все еще получаю: –

+0

@ user1438352: У меня есть upda и проверил его локально; он работает правильно для меня сейчас. –

+0

Должно быть, я делаю что-то неправильно. Я все еще получаю: ТипError: <__ main __. Объект EqtlByGene в 0x10964e890> не является сериализуемым JSON –

2

Если вы посмотрите на the docs for the json module, в нем упоминается, что вы можете subclass JSONEncoder to override its default method и добавьте поддержку типов там. Это был бы самый общий способ справиться с этим, если вы собираетесь сериализовать несколько разных структур, которые могут содержать ваши объекты.

Если вы хотите использовать jsonify, то, вероятно, проще преобразовать объекты в простые типы заблаговременно (например, определив свой собственный метод в классе, как предполагает Мартийн).

+0

Прошу прощения, я новичок в python. Я смотрю на эти документы, и это просто тарабарщина. Не могли бы вы привести пример? –

+0

@MartijnPieters Я думал, что 'jsonify' передал' * args, ** kwargs' через? Во всяком случае, это может быть время, когда лучше не использовать jsonify. – Amber

+0

@Amber: Да, и эти аргументы передаются 'dict()' и *, которые затем передаются 'json.dumps()'. –

Смежные вопросы