Tanggapan saya kembali dari MongoDB setelah menanyakan fungsi agregat pada dokumen menggunakan Python, Ia mengembalikan tanggapan yang valid dan saya dapat mencetaknya tetapi tidak dapat mengembalikannya.
Kesalahan:
TypeError: ObjectId('51948e86c25f4b1d1c0d303c') is not JSON serializable
Mencetak:
{'result': [{'_id': ObjectId('51948e86c25f4b1d1c0d303c'), 'api_calls_with_key': 4, 'api_calls_per_day': 0.375, 'api_calls_total': 6, 'api_calls_without_key': 2}], 'ok': 1.0}
Tetapi ketika saya mencoba untuk kembali:
TypeError: ObjectId('51948e86c25f4b1d1c0d303c') is not JSON serializable
Ini adalah panggilan RESTfull:
@appv1.route('/v1/analytics')
def get_api_analytics():
# get handle to collections in MongoDB
statistics = sldb.statistics
objectid = ObjectId("51948e86c25f4b1d1c0d303c")
analytics = statistics.aggregate([
{'$match': {'owner': objectid}},
{'$project': {'owner': "$owner",
'api_calls_with_key': {'$cond': [{'$eq': ["$apikey", None]}, 0, 1]},
'api_calls_without_key': {'$cond': [{'$ne': ["$apikey", None]}, 0, 1]}
}},
{'$group': {'_id': "$owner",
'api_calls_with_key': {'$sum': "$api_calls_with_key"},
'api_calls_without_key': {'$sum': "$api_calls_without_key"}
}},
{'$project': {'api_calls_with_key': "$api_calls_with_key",
'api_calls_without_key': "$api_calls_without_key",
'api_calls_total': {'$add': ["$api_calls_with_key", "$api_calls_without_key"]},
'api_calls_per_day': {'$divide': [{'$add': ["$api_calls_with_key", "$api_calls_without_key"]}, {'$dayOfMonth': datetime.now()}]},
}}
])
print(analytics)
return analytics
db terhubung dengan baik dan koleksi ada di sana juga dan saya mendapatkan kembali hasil yang diharapkan yang valid tetapi ketika saya mencoba mengembalikannya memberi saya kesalahan Json. Ada ide bagaimana mengubah respon kembali menjadi JSON. Terima kasih
if isinstance(o, ObjectId): return str(o)
sebelumnyareturn
di metodedefault
.from bson import ObjectId
, sehingga semua orang dapat menyalin-tempel lebih cepat? Terima kasih!str
? Apa yang salah dengan pendekatan itu?Pymongo menyediakan json_util - Anda dapat menggunakannya sebagai gantinya untuk menangani jenis BSON
sumber
from bson import json_util
json.loads(json_util.dumps(user_collection))
^ ini berfungsi setelah menginstal python-bsonjs denganpipenv install python-bsonjs
Contoh sebenarnya dari json_util .
Tidak seperti jsonify Flask, "dumps" akan mengembalikan string, jadi tidak bisa digunakan sebagai pengganti 1: 1 dari jsonify Flask.
Tetapi pertanyaan ini menunjukkan bahwa kita dapat membuat serial menggunakan json_util.dumps (), mengkonversi kembali ke dict menggunakan json.loads () dan terakhir memanggil jsonify Flask di atasnya.
Contoh (berasal dari jawaban pertanyaan sebelumnya):
Solusi ini akan mengonversi ObjectId dan lainnya (yaitu Biner, Kode, dll) menjadi string yang setara seperti "$ oid."
Keluaran JSON akan terlihat seperti ini:
sumber
Ini adalah contoh contoh untuk mengubah BSON menjadi objek JSON. Anda bisa mencobanya.
sumber
Sebagian besar pengguna yang menerima kesalahan "tidak dapat disambung JSON" hanya perlu menentukan
default=str
saat menggunakanjson.dumps
. Sebagai contoh:Ini akan memaksa konversi ke
str
, mencegah kesalahan. Tentu saja kemudian lihat keluaran yang dihasilkan untuk memastikan bahwa itu yang Anda butuhkan.sumber
Sebagai pengganti cepat, Anda dapat beralih
{'owner': objectid}
ke{'owner': str(objectid)}
.Tetapi menentukan milik Anda sendiri
JSONEncoder
adalah solusi yang lebih baik, itu tergantung pada kebutuhan Anda.sumber
Posting di sini karena menurut saya mungkin berguna untuk orang yang menggunakan
Flask
withpymongo
. Ini adalah pengaturan "praktik terbaik" saya saat ini untuk mengizinkan flask mengatur tipe data pymongo bson.mongoflask.py
app.py
Mengapa ini alih-alih melayani BSON atau mongod extended JSON ?
Menurut saya, melayani mongo khusus JSON membebani aplikasi klien. Sebagian besar aplikasi klien tidak akan peduli menggunakan objek mongo dengan cara yang rumit. Jika saya melayani json diperpanjang, sekarang saya harus menggunakannya di sisi server, dan sisi klien.
ObjectId
danTimestamp
lebih mudah untuk digunakan sebagai string dan ini membuat semua kegilaan mongo marshalling ini dikarantina ke server.Saya pikir ini tidak terlalu memberatkan untuk bekerja dengan sebagian besar aplikasi daripada.
sumber
Beginilah cara saya baru-baru ini memperbaiki kesalahan
sumber
Saya tahu saya terlambat memposting tetapi saya pikir itu akan membantu setidaknya beberapa orang!
Kedua contoh yang disebutkan oleh tim dan defuz (yang dipilih terbanyak) berfungsi dengan baik. Namun, ada perbedaan menit yang terkadang bisa signifikan.
Pymongo menyediakan json_util - Anda dapat menggunakannya sebagai gantinya untuk menangani jenis BSON
Keluaran: {"_id": {"$ oid": "abc123"}}
Keluaran: {"_id": "abc123"}
Meski cara pertama terlihat sederhana, kedua cara tersebut membutuhkan tenaga yang sangat minim.
sumber
pytest-mongodb
plugin saat membuat perlengkapandalam kasus saya, saya membutuhkan sesuatu seperti ini:
sumber
object['_id'] = str(object['_id'])
Jsonify Flask menyediakan peningkatan keamanan seperti yang dijelaskan dalam Keamanan JSON . Jika pembuat enkode khusus digunakan dengan Flask, sebaiknya pertimbangkan poin-poin yang dibahas dalam Keamanan JSON
sumber
Saya ingin memberikan solusi tambahan yang meningkatkan jawaban yang diterima. Saya sebelumnya telah memberikan jawaban di utas lain di sini .
sumber
Jika Anda tidak memerlukan _id dari catatan, saya akan merekomendasikan untuk tidak menyetelnya saat menanyakan DB yang akan memungkinkan Anda untuk mencetak catatan yang dikembalikan secara langsung, mis.
Untuk menghapus _id saat membuat kueri dan kemudian mencetak data dalam satu lingkaran, Anda menulis sesuatu seperti ini
sumber
SOLUSI untuk: mongoengine + marshmallow
Jika Anda menggunakan
mongoengine
danmarshamallow
kemudian solusi ini mungkin berlaku untuk Anda.Pada dasarnya, saya mengimpor
String
bidang dari marshmallow, dan saya menimpa defaultSchema id
untukString
dikodekan.sumber
sumber
Jika Anda tidak ingin
_id
menanggapi, Anda dapat memfaktorkan ulang kode Anda seperti ini:Ini akan menghapus
TypeError: ObjectId('') is not JSON serializable
kesalahan.sumber