Мой ответ от MongoDB после запроса агрегированной функции в документе с использованием Python. Он возвращает действительный ответ, и я могу его распечатать, но не могу вернуть.
Ошибка:
TypeError: ObjectId('51948e86c25f4b1d1c0d303c') is not JSON serializable
Распечатать:
{'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}
Но когда я пытаюсь вернуться:
TypeError: ObjectId('51948e86c25f4b1d1c0d303c') is not JSON serializable
Это вызов 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 хорошо связан, и коллекция тоже есть, и я получил действительный ожидаемый результат, но когда я пытаюсь вернуть, он дает мне ошибку Json. Есть идеи, как преобразовать ответ обратно в JSON. Спасибо
if isinstance(o, ObjectId): return str(o)
доreturn
методаdefault
.from bson import ObjectId
, чтобы все могли копировать-вставить еще быстрее? Спасибо!str
? Что плохого в таком подходе?Pymongo предоставляет json_util - вы можете использовать его вместо этого для обработки типов BSON
источник
from bson import json_util
json.loads(json_util.dumps(user_collection))
^ это сработало после установки python-bsonjs сpipenv install python-bsonjs
Актуальный пример из json_util .
В отличие от jsonify из Flask, «дамп» возвращает строку, поэтому его нельзя использовать в качестве замены 1: 1 для jsonify из Flask.
Но этот вопрос показывает, что мы можем сериализовать с помощью json_util.dumps (), преобразовать обратно в dict с помощью json.loads () и, наконец, вызвать для него jsonify Flask.
Пример (полученный из ответа на предыдущий вопрос):
Это решение преобразует ObjectId и другие объекты (например, двоичный, код и т. Д.) В строковый эквивалент, например «$ oid».
Вывод JSON будет выглядеть так:
источник
Большинству пользователей, которые получают ошибку «не сериализуемый JSON», просто нужно указать
default=str
при использованииjson.dumps
. Например:Это приведет к преобразованию в
str
, предотвращая ошибку. Конечно, затем посмотрите на сгенерированный результат, чтобы убедиться, что это то, что вам нужно.источник
Это примерный пример преобразования BSON в объект JSON. Вы можете попробовать это.
источник
В качестве быстрой замены вы можете перейти
{'owner': objectid}
на{'owner': str(objectid)}
.Но определение собственного
JSONEncoder
- лучшее решение, оно зависит от ваших требований.источник
Публикация здесь, поскольку я думаю, может быть полезна для людей, использующих
Flask
сpymongo
. Это моя текущая «лучшая практика», позволяющая flask маршалировать типы данных pymongo bson.mongoflask.py
app.py
Почему это вместо обслуживания BSON или расширенного JSON mongod ?
Я думаю, что обслуживание специального JSON для монго ложится бременем на клиентские приложения. Большинство клиентских приложений не заботятся об использовании объектов mongo каким-либо сложным образом. Если я использую расширенный json, теперь мне придется использовать его на стороне сервера и на стороне клиента.
ObjectId
и сTimestamp
ними легче работать как со строками, и это держит все это безумие монго-маршаллинга в карантине на сервере.Я думаю, что для большинства приложений это менее обременительно, чем.
источник
Вот как я недавно исправил ошибку
источник
Я знаю, что отправляю сообщение поздно, но подумал, что это поможет хотя бы некоторым людям!
Оба примера, упомянутые tim и defuz (которые получили наибольшее количество голосов), работают отлично. Однако есть небольшая разница, которая временами может быть значительной.
Pymongo предоставляет json_util - вы можете использовать его вместо этого для обработки типов BSON
Вывод: {"_id": {"$ oid": "abc123"}}
Вывод: {"_id": "abc123"}
Несмотря на то, что первый метод выглядит простым, оба метода требуют минимальных усилий.
источник
pytest-mongodb
плагина при создании светильниковв моем случае мне понадобилось что-то вроде этого:
источник
object['_id'] = str(object['_id'])
Jsonify Flask обеспечивает повышение безопасности, как описано в разделе Безопасность JSON . Если с Flask используется настраиваемый кодировщик, лучше учитывать моменты, обсуждаемые в разделе « Безопасность JSON».
источник
Я хотел бы предложить дополнительное решение, улучшающее принятый ответ. Я ранее давал ответы в другой теме здесь .
источник
Если вам не понадобится _id записей, я рекомендую отключить его при запросе БД, что позволит вам напрямую печатать возвращенные записи, например
Чтобы отключить _id при запросе, а затем печатать данные в цикле, вы пишете что-то вроде этого
источник
РЕШЕНИЕ для: mongoengine + зефир
Если вы используете
mongoengine
и,marshamallow
то это решение может быть применимо для вас.По сути, я импортировал
String
поле из зефира и перезаписал значениеSchema id
по умолчанию дляString
кодирования.источник
источник
Если вы не хотите
_id
получать ответ, вы можете реорганизовать свой код примерно так:Это устранит
TypeError: ObjectId('') is not JSON serializable
ошибку.источник