2013-07-13 32 views
10

時,我得到'TypeError:ObjectId('')不是JSON序列化'我分叉了Flask示例Minitwit來使用MongoDB,它在Flask 0.9上正常工作,但在升級到0.10之後。 1當我嘗試設置會話ID時,登錄時出現錯誤。當使用Flask 0.10.1

看起來有changes Flask 0.10.1與json相關。

代碼片段:

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

在我github回購的完整代碼。

基本上,我將Flask會話ID設置爲來自MongoDB的用戶_id。

我試着從這SO question沒有成功的第一個兩個解決方案。

好,做會議[「_ ID」] = STR(用戶[「_身份證」])擺脫了錯誤信息,我適當地重定向到時間軸頁面,但我實際上沒有登錄。

我該如何解決這個問題?

編輯:追溯的複製/粘貼:http://pastebin.com/qa0AL1fk

謝謝。

回答

12

編輯的簡單情況:即使容易固定。你甚至不需要做任何JSON編碼/解碼。

只需保存會話[「_ ID」]作爲一個字符串:

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

然後無處不在,你想要做的會話[「_身份證」]你有一個的ObjectId把它包起來(的東西),所以它作爲ObjectId對象傳遞給MongoDB。

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

到:

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

你可以看到我的github repo用於修復完整的差異。

如果有人關心爲什麼TypeError:ObjectId('')不是JSON序列化'「問題出現在Flask 0.10.1中,這是因爲他們改變了會話存儲的方式。它們現在被存儲爲JSON,因爲MongoDB中的'_id'對象不是標準的JSON,它無法序列化會話令牌,從而導致TypeError。閱讀關於這裏的變化:http://flask.pocoo.org/docs/upgrading/#upgrading-to-010

9

默認情況下,JSON僅支持序列化(編碼/解碼)一組有限的對象類型。你可以擴展python JSON的解碼器/編碼器來處理這種情況。

在其編碼包含對象ID的對象而言,例如,當的ObjectID創建客戶端,這將沿着一些等待服務器傳遞,嘗試:

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 

然後,在你的代碼,推數據客戶端之前 - >服務器上運行:

json.dumps(obj, cls=Encoder) 

服務器端,如果我們知道我們正在處理蒙戈文檔,(用「_id」鍵字典對象),我們可以定義一個JSON解碼器鉤如下所示:

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

而且使用類似呼叫稱它爲以下內容:

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

你可能需要適應這個代碼的,但對於通過

0

這是我最近怎麼固定的錯誤

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

toString將其轉換爲字符串,並且可以存儲到會話:

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

替代 session['_id'] = str(user['_id'])

以上修復了我的錯誤。