QT Reading a JSON file and storing and retriving values - c++

I am trying to read a json file like shown below in QT. Can someone suggest a way to obtain values from json object and store them in separate containers or array such as test_cell2.CELLS[0] or some way so that nesting can also be taken care of and also I can access them easily after parsing the file
"test_cells2" : {
"CELLS" : {
"cell_0" : {
"prettyName" : "cell_1",
"CELLS" : {
"cell_1" : {
"prettyName" : "cell_1",
"type" : "default",
},
},
},
"cell_1" : {
"prettyName" : "cell_1",
"type" : "default",
},
"cell_2" : {
"type" : "text cell ko",
},
"cell_3" : {
"prettyName" : "cell_3",
"type" : "default",
},
"cell_4" : {
"data" : {
"settings" : {
"EXEC_PARAMETERS" : {
"defaultQueue" : "batch",
"environment" : {
"blabla" : "blabla2",
},
},
},
},
"type" : "parallel_test",
},
},
},

Take a look at this function
QJsonDocument::fromJson(QByteArray)
http://doc.qt.io/qt-5/qjsondocument.html#fromJson
Then use QJsonDocument::object() and you can use keys to get your values:
QJsonDocument doc = QJsonDocument::fromJson(QByteArray);
QJsonObject root = doc.object();
foreach(QJsonValue element, root["CELLS"].toArray()){
QJsonObject node = element.toObject();
node["whatEver"];
}

If you Qt Version > 5.5 check QJSonDocument, http://doc.qt.io/qt-5/qjsondocument.html.
An Example:
// Just read it from a file... or copy here
const QString yourJSON = "...";
const QJsonDocument jsonDoc = QJsonDocument::fromJson(yourJSON.toLocal8Bit());
const QVariantMap map = jsonDoc.toVariant().toMap();
To take care of nesting of CELLS inside CELLS, first load your CELLS array:
// Start read your parameter
const QVariant testCells2 = map["test_cells2"].toVariant();
const QVariantList CELLS = testCells2.toList();
// Now, we have a list available CELLS, check one be one
foreach (const QVariant& cell, CELLS) {
const QVariantMap wrapped = cell.toMap();
qDebug() << "Pretty Name: " << wrapped["prettyName"].toString();
qDebug() << "Type: " << wrapped["type"].toString();
const hasList = !wrapped["CELLS"].toList().isEmpty();
qDebug() << "Has child list? << hasList;
if (hasList) {
// Start another loop to check the child list.
}
}

Related

How to access array elements inside JSON in nlohman json in c++?

I have following JSON file
{
"list" :
{
"type" : "school",
"students" : [
{
"name" : "root",
"marks" : "100"
},
{
"name" : "joe",
"version" : "100"
}]
}
}
So in code I have parsed this JSON file and assigned this JSON object to JSON::student. So I am able to assign first element to string like this :
std::string type = student["list"]["type"];
and it works. SO similarly I want to do for "name" and "marks" in "students" array. How can I do that?
You can simply iterate over all the elements with iterators
std::string const str = "{ \"list\" : { \"type\" : \"school\", \"students\" : [ "
"{ \"name\" : \"root\", \"marks\" : \"100\"}, "
"{ \"name\" : \"joe\", \"version\" : \"100\" } "
"] } }";
nlohmann::json const js = nlohmann::json::parse(str);
nlohmann::json const& ja = js["list"]["students"];
for (auto it = ja.begin(); it != ja.end(); ++it) {
// For each individual element (root, joe, ...)
if (it->contains("name")) {
std::string const name = (*it)["name"].get<std::string>();
// Do something with the name
}
if (it->contains("marks")) {
std::string const marks = (*it)["marks"].get<std::string>();
// Do something with the marks
}
if (it->contains("version")) {
std::string const version = (*it)["version"].get<std::string>();
// Process version
}
// ...
}

Is there an node like statement available in mongodb

I want to filter the decimal value in child array of json file.In below sample code i want to apply the like function to get the json value like(t1,t2) in below sample file.
Sample code:
db.getCollection('temp').find({},{"temp.text./.*t.*/.value":1})
Sample Json file:
{
"_id" :0"),
"temp" : {
"text" : {
"t1" : {
"value" : "960"
},
"t2" : {
"value" : "959"
},
"t3" : {
"value" : "961"
},
"t4" : {
"value" : "962"
},
"t5" : {
"value" : "6.0"
}
}
}
}
MongoDB doesn't have a way to filter field names directly other than projection, which is exact match only.
However, using aggregation you can use $objectToArray, which would convert the object {"t1" : {"value" : "960"}} to [{"k":"t1","v":{"value":"960"}}]. You can then filter based on the value of k, and use $arrayToObject to convert the entries left back into an object.
.aggregate([
{$addFields:{
"temp.text":{
$arrayToObject:{
$filter:{
input:{$objectToArray:"$temp.text"},
cond:{
$regexMatch:{
input:"$$this.k",
regex:/t/
}
}
}
}
}
}}
])
Playground

update dynamodb list item

This seems like it should be really simple but I haven't found any examples or documentation. I've got a dynamodb table that looks like this:
record 1: {name, email, items[{product}, {item2}, {item3]}
record 2: (name, email, items[{product}, {item2}, {item3]}
I need to be able to update items elements, i.e., update item1 object in record 1. I can do this with the following code by hardcoding the list array element, but I can't figure out how to pass the item number into the update expression :
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : { "S" : "${context.arguments.input.id}" }
},
"update" : {
"expression" : "SET #items[0].#product= :productVal",
"expressionNames" : {
"#product": "product",
},
"expressionValues" : {
":productVal": { "S" : "${context.arguments.input.product}" },
}
}
Have you tried something like:
"update" : {
"expression" : "SET #items[:idx].#product= :productVal",
"expressionNames" : {
"#product": "product",
},
"expressionValues" : {
":productVal": { "S" : "${context.arguments.input.product}" },
":idx": { "N" : 0 }
}
}

Converting a BSON document containing an array to JSON, removes the array from the converted JSON (C++)

I have a document that looks like this:
{
"_id" : ObjectId("5bd37e0128f41363c0006ac2"),
"source" : "Forge",
"data" : [
{
"symbol" : "EURUSD",
"bid" : 1.14021,
"ask" : 1.14024,
"price" : 1.14023,
"timestamp" : 1540587008
}
]
}
I want to get the data part out of the bson document, which I'm doing by this code:
auto dataDocument = view["data"].get_value().get_document();
auto textMessage = bsoncxx::to_json(dataDocument);
However the output when field data is an array as in the example is this:
{
"0": {
"symbol": "EURUSD",
"bid": 1.1405199999999999783,
"ask": 1.1405300000000000438,
"price": 1.1405300000000000438,
"timestamp": 1540580136
}
}
Instead of this (correct):
[{
"symbol": "EURUSD",
"bid": 1.14056,
"ask": 1.14057,
"price": 1.14057,
"timestamp": 1540580927
}
]
How come the brackets are removed and instead a "0" field is put there instead?
If I do a to_json on the whole document the array is kept, its only when I do to_json on the field data which is an array the error happens.
Any ideas?
Update, here's a working example which reproduce my issue:
#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);
}
I believe the problem is here: get_value().get_document(). Try making that say get_value().get_array() instead. Also note that you should be checking the type of the value returned by get_value before calling any methods on it. This is working more by good luck than by good design. The reason that you are seeing a literal zero there is because BSON arrays are represented as documents with integral keys. You have, effectively, cast an array to a document, so it is printing as a document with numeric keys, instead of an array as intended.

Using $push operator for update MongoDB document

I have MongoDB document with structure like this:
{
"_id" : ObjectId("56ebce0d1e3c51fe6a5053f3"),
"timestamp" : 1458294285,
"values" : [
{
"offset" : 132,
"packets" : [
{
"type" : "type1",
"data" : "some_data1"
},
{
"type" : "type2",
"data" : "some_data2"
}
]
}
}
I use it for storage time series data.
I want to create the query which insert a packet in packets array.
I use MongoDB c++ legacy driver 1.1.0.
When I will execute twice code below with equal timestamp and offset:
mongo::BSONObj query = BSON("timestamp" << timestamp);
mongo::BSONObj mainObj =
BSON ("$push" << BSON("values" << BSON("offset" << timestampOffset <<
"packets" << BSON_ARRAY(obj))));
connection.update(collectionName, query, mainObj, true);
I have result like this:
{
"_id" : ObjectId("56f90c1a3b20b7c1f61dccf7"),
"timestamp" : 1459080000,
"values" : [
{
"offset" : 68457,
"packets" : [
{
"type" : "type1",
"data" : "some_data1"
}
]
},
{
"offset" : 68457,
"packets" : [
{
"type" : "type2",
"data" : "some_data2"
}
]
}
]
}
Can somebody help me create right query for insert data into the document with specific structure?