22

MongodbとPython(Flask)で問題が発生しています。

このapi.pyファイルがあり、すべてのリクエストとレスポンスをJSONで実行したいので、そのように実装します。

#
# Imports
#

from datetime import datetime
from flask import Flask
from flask import g
from flask import jsonify
from flask import json
from flask import request
from flask import url_for
from flask import redirect
from flask import render_template
from flask import make_response
import pymongo
from pymongo import Connection
from bson import BSON
from bson import json_util

#
# App Create
#

app = Flask(__name__)
app.config.from_object(__name__)

#
# Database
#

# connect
connection = Connection()
db = connection['storage']
units = db['storage']


#
# Request Mixins
#

@app.before_request
def before_request():
    #before
    return

@app.teardown_request
def teardown_request(exception):
    #after
    return


#
# Functions
#

def isInt(n):
    try:
        num = int(n)
        return True
    except ValueError:
        return False

def isFloat(n):
    try:
        num = float(n)
        return True
    except ValueError:
        return False

def jd(obj):
    return json.dumps(obj, default=json_util.default)

def jl(obj):
    return json.loads(obj, object_hook=json_util.object_hook)

#
# Response
#

def response(data={}, code=200):
    resp = {
        "code" : code,
        "data" : data
    }
    response = make_response(jd(resp))
    response.headers['Status Code'] = resp['code']
    response.headers['Content-Type'] = "application/json"
    return response


#
# REST API calls
#

# index
@app.route('/')
def index():
    return response()

# search
@app.route('/search', methods=['POST'])
def search(): 
    return response()

# add
@app.route('/add', methods=['POST'])
def add():
    unit = request.json
    _id = units.save(unit)
    return response(_id)

# get
@app.route('/show', methods=['GET'])
def show():
    import pdb; pdb.set_trace();
    return response(db.units.find())

#
# Error handing
#

@app.errorhandler(404)
def page_not_found(error):
    return response({},404)


#
# Run it!
#

if __name__ == '__main__':
    app.debug = True
    app.run()

ここでの問題は、mongoとの間で送受信されるjsonエンコーディングデータです。request.jsonを保存用の辞書として渡すことで、追加ルートを「ハック」できたようです。それで問題ありません...問題は/showです。このコードは機能しません...ロギングを行うと、

TypeError: <pymongo.cursor.Cursor object at 0x109bda150> is not JSON serializable

何か案は?コードの残りの部分に関する提案も歓迎しますが、JSONは私を殺します。

前もって感謝します!

4

6 に答える 6

37

@ErenGüven は、この json シリアライズの問題を解決するための優れた手動アプローチを示していますが、pymongo にはこれを達成するためのユーティリティが付属しています。私はこれを自分の django mongodb プロジェクトで使用しています。

import json
from bson import json_util

json_docs = []
for doc in cursor:
    json_doc = json.dumps(doc, default=json_util.default)
    json_docs.append(json_doc)

または単に:

json_docs = [json.dumps(doc, default=json_util.default) for doc in cursor]

そして、それらをjsonから再び取得するには:

docs = [json.loads(j_doc, object_hook=json_util.object_hook) for j_doc in json_docs]

ヘルパー ユーティリティはjson、カスタム mongodb オブジェクトの処理方法を指示します。

于 2012-07-02T01:33:30.677 に答える
21

に渡すときにdb.units.find()responseオブジェクトpymongo.cursor.Cursorjson.dumps... に渡しますが、json.dumpsそれを JSON にシリアル化する方法がわかりません。カーソルを反復処理して結果を取得し、実際のオブジェクトを取得してみてください。

[doc for doc in db.units.find()]
于 2012-07-01T22:58:46.533 に答える
4

MongoDB ドキュメントを JSON にエンコードするために、以下のカバーbson.objectid.ObjectIddatetime.datetimeタイプと同様のアプローチを使用します。

class CustomEncoder(json.JSONEncoder):
    """A C{json.JSONEncoder} subclass to encode documents that have fields of
    type C{bson.objectid.ObjectId}, C{datetime.datetime}
    """
    def default(self, obj):
        if isinstance(obj, bson.objectid.ObjectId):
            return str(obj)
        elif isinstance(obj, datetime.datetime):
            return obj.isoformat()
        return json.JSONEncoder.default(self, obj)

enc = CustomEncoder()
enc.encode(doc)

カーソルに関しては、最初に反復してドキュメントを取得する必要があります。

于 2012-07-02T01:14:03.933 に答える