2013-07-13 13 views
10

Ho biforcato l'esempio Flask, Minitwit, per lavorare con MongoDB e funzionava bene su Flask 0.9, ma dopo l'aggiornamento a 0.10. 1 Ricevo l'errore nel titolo quando effettuo l'accesso quando provo a impostare l'ID della sessione.Ottenere 'TypeError: ObjectId (' ') non è serializzabile JSON' quando si utilizza Flask 0.10.1

Sembra che ci fosse changes in Flask 0.10.1 relativo a json.

Codice frammento:

user = db.minitwit.user.find_one({'username': request.form['username']}) 
session['_id'] = user['_id'] 

codice completo nella mia github pronti contro termine.

Fondamentalmente, ho impostato l'ID della sessione Flask su _id dell'utente da MongoDB.

Ho provato le prime due soluzioni da questo SO question senza successo.

Beh, facendo sessione [ '_ id'] = str (user [ '_ id']) si libera del messaggio di errore e sto correttamente reindirizzato alla pagina di linea temporale, ma io non sono in realtà il login.

Come posso risolvere questo problema?

EDIT: copia/incolla del traceback: http://pastebin.com/qa0AL1fk

Grazie.

risposta

12

EDIT: Ancora più facile risolvere. Non è nemmeno necessario eseguire alcuna codifica/decodifica JSON.

Basta salvare la sessione [ '_ id'] come una stringa:

user = db.minitwit.user.find_one({'username': request.form['username']}) 
session['_id'] = str(user['_id']) 

E poi ovunque si vuole fare qualcosa con la sessione [ '_ id'] è necessario avvolgerlo con ObjectId() in modo è passato come oggetto ObjectId a MongoDB.

if '_id' in session: 
    g.user = db.minitwit.user.find_one({'_id': session['_id']}) 

a:

if '_id' in session: 
    g.user = db.minitwit.user.find_one({'_id': ObjectId(session['_id'])}) 

È possibile vedere l'intero diff per applicare la correzione mia github repo.

Se qualcuno vuole sapere perché "TypeError: ObjectId ('') non è" serializzabile "JSON" apparso "in Flask 0.10.1, è perché hanno cambiato il modo in cui le sessioni sono archiviate. Ora sono archiviati come JSON, in quanto l'oggetto '_id' in MongoDB non è un JSON standard, non è riuscito a serializzare il token di sessione, dando così l'errore TypeError. Leggi il cambiamento qui: http://flask.pocoo.org/docs/upgrading/#upgrading-to-010

9

JSON supporta solo la serializzazione (codifica/decodifica) di un set limitato di tipi di oggetti per impostazione predefinita. Potresti estendere il codificatore/codificatore JSON di Python per gestire questa situazione.

In termini di codifica di un oggetto che contiene l'IDOggetto, ad esempio, quando objectIds si creano lato client, che sarà passato insieme ad un server in attesa, provare:

import json 
from bson.objectid import ObjectId 

class Encoder(json.JSONEncoder): 
    def default(self, obj): 
     if isinstance(obj, ObjectId): 
      return str(obj) 
     else: 
      return obj 

Poi, nel codice, prima di spingere il cliente di dati - server>, eseguire:

json.dumps(obj, cls=Encoder) 

lato server, se sappiamo abbiamo a che fare con documenti Mongo, (oggetto dizionario con una chiave '_id'), possiamo definire un gancio jSON decoder come il seguente:

def decoder(dct): 
    for k, v in dct.items(): 
     if '_id' in dct: 
      try: 
       dct['_id'] = ObjectId(dct['_id']) 
      except: 
       pass 
     return dct 

e chiamare utilizzando una chiamata come la seguente:

doc = json.loads(in_doc, object_hook=decoder) 

avrete probabilmente bisogno di adattare questo codice un po ', ma per il semplice caso di passaggio

0

Questo è il modo che ho di recente riparato l'errore

@app.route('/') 
def home(): 
    docs = [] 
    for doc in db.person.find(): 
     doc.pop('_id') 
     docs.append(doc) 
    return jsonify(docs) 
0

toString converte alla stringa e che può memorizzato sessione:

session['_id'] = user['_id'].toString() 

alternativa session['_id'] = str(user['_id'])

Quanto sopra ha corretto l'errore per me.

Problemi correlati