Есть ли лучший способ напрямую конвертировать документ Rust BSON в JSON?

Идея заключается в получении курсора из Mongo и сериализации набора результатов в JSON в виде строки. У меня есть рабочий код:

extern crate bson;
extern crate mongodb;

use mongodb::db::ThreadedDatabase;
use mongodb::{Client, ThreadedClient};

extern crate serde;
extern crate serde_json;

fn main() {
    let client =
        Client::connect("localhost", 27017).expect("Failed to initialize standalone client.");

    let coll = client.db("foo").collection("bar");

    let cursor = coll.find(None, None).ok().expect("Failed to execute find.");

    let docs: Vec<_> = cursor.map(|doc| doc.unwrap()).collect();

    let serialized = serde_json::to_string(&docs).unwrap();

    println!("{}", serialized);
}

Есть лучший способ сделать это? Если нет, я закрою эту ветку.

1 ответ

Это такая ситуация, котораяserde-transcodeбыл сделан для. Что он делает, так это конвертирует напрямую междуserdeформаты. Как это работает: он принимает a и a , а затем напрямую вызывает соответствующую функцию сериализации для каждого десериализованного элемента. Концептуально это немного похоже на использованиеserde_json::Valueв качестве промежуточного формата, но может включать некоторую дополнительную информацию о типе, если она доступна во входном формате.

К сожалению, bsonящик не выставляется или bson::ser::raw::Serializerтак что на данный момент это невозможно. Если вы посмотрите в документации,DeserializerиSerializerна самом деле ссылаются на разные структуры, которые обрабатывают преобразование в и изBsonперечисление

Еслиbson::de::raw::Deserializerбыл общедоступным, то этот код имел бы желаемый эффект. Надеюсь, это будет полезно всем, у кого есть похожая проблема (или тем, кто этого хочет достаточно, чтобы поднять вопрос в своем репозитории).

      let mut buffer = Vec::new();

// Manually add array separators because the proper way requires going through
// DeserializeSeed and that is a whole other topic.
buffer.push(b'[');

while cursor.advance().await? {
    let bytes = cursor.current().as_bytes();

    // Create deserializer and serializer
    let deserializer = bson::de::raw::Deserializer::new(bytes, false);
    let serializer = serde_json::Serializer::new(&mut buffer);
    
    // Transcode between formats
    serde_transcode::transcode(deserializer, serializer).unwrap();

    // Manually add array separator
    buffer.push(b',');
}

// Remove trailing comma and add closing bracket
if buffer.len() > 1 {
    buffer.pop();
}
buffer.push(']');

// Do something with the result
println!("{}", String::from_utf8(buffer).unwrap())
Другие вопросы по тегам