PyMongo json_util.dumps перезаписывает представление ObjectId - PullRequest
1 голос
/ 03 октября 2019

bson.json_util предоставляет функции для преобразования в канонический или расслабленный формат JSON. Однако оба они придерживаются одного и того же представления ObjectId:

from PyMongo import MongoClient
from bson.objectid import ObjectId
from bson import json_util
from bson.json_util import RELAXED_JSON_OPTIONS
from bson.json_util import CANONICAL_JSON_OPTIONS, DEFAULT_JSON_OPTIONS


db = MongoClient(URL)['DB_NAME']
mongo_query_result = db.collection.find_one({'_id': ObjectId('ID')}, 
                                                   {'_id': 1})

# returns {'_id': ObjectId('ID')}

print(json_util.dumps(mongo_query_result, json_options=RELAXED_JSON_OPTIONS))
print(json_util.dumps(mongo_query_result, json_options=CANONICAL_JSON_OPTIONS))
print(json_util.dumps(mongo_query_result, json_options=DEFAULT_JSON_OPTIONS))

# Results
{"_id": {"$oid": "ID"}}
{"_id": {"$oid": "ID"}}
{"_id": {"$oid": "ID"}}

# Desired Output
{"_id": "ID"}

Проблема в том, что он не соответствует результатам, которые я получаю в prod env. Я использую PyMongo только для построения тестовых случаев, фактический формат prod:

{'_id': "ID", ..etc}

Я немного посмотрел в документации более здесь , и вот результаты:

  1. И CANONICAL_JSON_OPTIONS, и RELAXED_JSON_OPTIONS придерживаются проблемного представления, спецификации здесь .
  2. Кажется, я не могу перезаписать его, потому что uuid_representation=PYTHON_LEGACY, а я не могунайти способ обойти это.

Есть ли что-то, что мне не хватает для преобразования PyMongo результата запроса в:

{'_id' : 'ID', ..}
# not
{'_id' : {'$oid' : 'ID'}, ..}

Я бы не хотел расширять свой код только для обработкидругой формат тестов.

1 Ответ

0 голосов
/ 03 октября 2019

В качестве обходного пути я смог добиться того же результата с помощью re регулярных выражений:

import re

def remove_oid(string):
    while True:
        pattern = re.compile('{\s*"\$oid":\s*(\"[a-z0-9]{1,}\")\s*}')
        match = re.search(pattern, string)
        if match:
            string = string.replace(match.group(0), match.group(1))
        else:
            return string

string = json_dumps(mongo_query_result)
string = remove_oid(string)

Это по существу заменяет CANONICAL_JSON на нормализованное и удаляет ключ-значение как просто значение.

Хотя это и делает работу, но она не идеальна, поскольку я манипулирую JSON как строкой и очень подвержен ошибкам, плюс не работает в Date или другом формате.

...