Преобразование документа BSON, содержащего массив в JSON, удаляет массив из преобразованного JSON (C ++) - PullRequest
0 голосов
/ 26 октября 2018

У меня есть документ, который выглядит так:

{
    "_id" : ObjectId("5bd37e0128f41363c0006ac2"),
    "source" : "Forge",
    "data" : [ 
        {
            "symbol" : "EURUSD",
            "bid" : 1.14021,
            "ask" : 1.14024,
            "price" : 1.14023,
            "timestamp" : 1540587008
        }
    ]
}

Я хочу получить часть данных из документа bson, что я делаю с помощью этого кода:

auto dataDocument = view["data"].get_value().get_document();
auto textMessage = bsoncxx::to_json(dataDocument);

Однако выходные данные, когда данные поля являются массивом, как в примере, выглядят так:

{
    "0": {
        "symbol": "EURUSD",
        "bid": 1.1405199999999999783,
        "ask": 1.1405300000000000438,
        "price": 1.1405300000000000438,
        "timestamp": 1540580136
    }
}

Вместо этого (правильно):

[{
        "symbol": "EURUSD",
        "bid": 1.14056,
        "ask": 1.14057,
        "price": 1.14057,
        "timestamp": 1540580927
    }
]

Почему удаляются скобки, и вместо этого вместо них ставится поле "0"?

Если я сделаю to_json для всего документа, массив будет сохранен, и только когда я сделаю to_json для данных поля, являющихся массивом, произойдет ошибка.

Есть идеи?

Обновление, вот рабочий пример, который воспроизводит мою проблему:

#include <mongocxx/instance.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>

int main()
{
    mongocxx::instance inst{};
    auto conn = mongocxx::client{ mongocxx::uri{} };
    auto collection = conn["QuantBot"]["test"];

    auto jsonDoc = R"(    
    {
        "source" : "Forge",
        "data" : [ 
            {
                "symbol" : "EURUSD",
                "bid" : 1.13875,
                "ask" : 1.13925,
                "price" : 1.139,
                "timestamp" : 1540758149
            }
        ]
    }
    )";

    auto bsonDocument = bsoncxx::from_json(jsonDoc);
    collection.insert_one(bsonDocument.view());

    auto cursor = std::make_unique<mongocxx::cursor>(collection.find({}));
    auto cursorIt = std::make_unique<mongocxx::cursor::iterator>(cursor->begin());
    auto view = bsoncxx::document::view(**cursorIt);
    auto dataDocument = view["data"].get_value().get_document();
    auto textMessage = bsoncxx::to_json(dataDocument);
}

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

использовать https://github.com/xyz347/mongoxclient и https://github.com/xyz347/x2struct легко сделать это.

полный пример

#include <iostream>

#include <mongocxx/client.hpp>
#include <mongocxx/uri.hpp>
#include <mongocxx/instance.hpp>

#include "mongoxclient.hpp"

mongocxx::instance instance{};

using namespace std;

struct Data {
    string symbol;
    float  bid;
    float  ask;
    float  price;
    int64_t timestamp;
    XTOSTRUCT(O(symbol, bid, ask, price, timestamp));
};

struct Doc {
    string source;
    vector<Data> data;
    XTOSTRUCT(O(source, data));
};


int main(int argc, char *argv[])
{
    mongocxx::uri uri("mongodb://test:test@127.0.0.1:27018/test");
    mongocxx::client client(uri);
    mongocxx::collection collect = client["test"]["test"];

    mongoxc::Collection col(collect);

    col.RemoveAll({});

    Doc d;
    d.source = "Forge";
    d.data.resize(1);
    d.data[0].symbol = "EURUSD";
    d.data[0].bid = 1.13875;
    d.data[0].ask = 1.13925;
    d.data[0].price = 1.139;
    d.data[0].timestamp = 1540758149;

    col.Insert(d);

    Doc get;
    col.Find({}).One(get);
    cout<<x2struct::X::tojson(get.data)<<endl;

    return 0;
}

вывод:

[{"symbol":"EURUSD","bid":1.1387499570846558,"ask":1.1392500400543213,"price":1.1390000581741334,"timestamp":1540758149}]

если вызов tojson так:

cout<<x2struct::X::tojson(get.data, "", 1, '\t')<<endl;

вывод:

[
        {
                "symbol": "EURUSD",
                "bid": 1.1387499570846558,
                "ask": 1.1392500400543213,
                "price": 1.1390000581741334,
                "timestamp": 1540758149
        }
]

нужно добавить флаги -DXTOSTRUCT_BSON при сборке этого кода

0 голосов
/ 29 октября 2018

Я считаю, что проблема здесь: get_value().get_document(). Попробуйте вместо этого сказать get_value().get_array(). Также обратите внимание, что вы должны проверять тип значения, возвращаемого get_value, прежде чем вызывать какие-либо методы для него. Это работает больше на удачу, чем на хороший дизайн. Причина, по которой вы видите буквальный ноль, заключается в том, что массивы BSON представлены в виде документов со встроенными ключами. Вы фактически преобразовали массив в документ, поэтому он печатает как документ с числовыми ключами, а не как массив по назначению.

...