I have a very quick question...
I'm using nlohmann's json library.
My issue is that when I go to print a element, the program stops responding.
My json file
{
"Consoleprinting": false,
"Input" : [{"Code" : [{"Name": "EC", "Keybind": "VK_NUMPAD1"}] }]
}
What I have tried.
nlohmann::json jsonData = nlohmann::json::parse(i_Read);
std::cout << jsonData << std::endl;
for (auto& array : jsonData["Input"]) {
std::cout << array["Code"] << std::endl;
}
^ This works but it prints out
[{"Name": "EC", "Keybind": "VK_NUMPAD1"}]
How can I get this it print out just the name?
array["Code"] is an array containing a single collection of key-value pairs, so you need to write:
std::cout << array["Code"][0]["Name"] << std::endl;
Related
While trying parsing a json string in my c++ code, using the library minijson, I got a code like that so far:
<<"version">> [&]() { result.setVersion(v.as_long()); }
<<"capabilities">> [&]()
{
parse_array(ctx, [&](value capability)
{
result.getCapabilities().push_back(capability.as_string());
});
}
the data should be stored on this struct:
struct block_template {
int version;
vector<string> capabilities;
...
}
the version value is stored correctly, but the vector is staying with size 0. I try visualize the data being read from the json string ( with cout << capability.as_string() << endl ) and it's display correctly, just not being stored in the data structure.
Anyone who already worked with this library can give a hint of what's wrong here?
Since the OP asks for examples using other libraries in the comments, I'll reply more generally.
In jsoncons, if the JSON member names and the C++ variable names were the same, you could use the macro JSONCONS_ALL_MEMBER_TRAITS to set up the mappings,
#include <iostream>
#include <jsoncons/json.hpp>
struct block_template {
int version;
std::vector<std::string> capabilities;
};
JSONCONS_ALL_MEMBER_TRAITS(block_template, version, capabilities)
int main()
{
std::string input = R"(
{
"version" : 1,
"capabilities" : ["foo","bar","baz"]
}
)";
auto result = jsoncons::decode_json<block_template>(input);
std::cout << "(1)\n" << "version: " << val.version << "\n";
for (auto& item : val.capabilities)
{
std::cout << "item: " << item << "\n";
}
std::string output;
jsoncons::encode_json(val, output, jsoncons::indenting::indent);
std::cout << "(2)\n" << output << "\n\n";
}
Output:
(1)
version: 1
item: foo
item: bar
item: baz
(2)
{
"capabilities": ["foo", "bar", "baz"],
"version": 1
}
And if the JSON and C++ names were different, you could use the macro JSONCONS_ALL_MEMBER_NAME_TRAITS instead,
JSONCONS_ALL_MEMBER_NAME_TRAITS(block_template, (version,"Version"),
(capabilities,"Capabilities"))
With this change, the output becomes:
(1)
version: 1
item: foo
item: bar
item: baz
(2)
{
"Capabilities": ["foo", "bar", "baz"],
"Version": 1
}
See this answer for more examples of libraries that decode JSON to C++ data structures and encode back again, including Martin York's interesting ThorsSerializer.
File:
{
"somestring":{
"a":1,
"b":7,
"c":17,
"d":137,
"e":"Republic"
},
}
how can I read the somestring value by jsoncpp?
Use the getMemberNames() method.
Json::Value root;
root << jsonString;
Json::Value::Members propNames = root.getMemberNames();
std::string firstProp = propNames[0];
std::cout << firstProp << '\n'; // should print somestring
If you want to see all the properties, you can loop through it using an iterator:
for (auto it: propNames) {
cout << "Property: " << *it << " Value: " << root[*it].asString() << "\n";
}
This simple loop will only work for properties whose values are strings. If you want to handle nested objects, like in your example, you'll need to make it recursive, which I'm leaving as an exercise for the reader.
My JSON file resembles this
{
"active" : false,
"list1" : ["A", "B", "C"],
"objList" : [
{
"key1" : "value1",
"key2" : [ 0, 1 ]
}
]
}
Using nlohmann json now, I've managed to store it and when I do a dump jsonRootNode.dump(), the contents are represented properly.
However I can't find a way to access the contents.
I've tried jsonRootNode["active"], jsonRootNode.get() and using the json::iterator but still can't figure out how to retrieve my contents.
I'm trying to retrieve "active", the array from "list1" and object array from "objList"
The following link explains the ways to access elements in the JSON. In case the link goes out of scope here is the code
#include <json.hpp>
using namespace nlohmann;
int main()
{
// create JSON object
json object =
{
{"the good", "il buono"},
{"the bad", "il cativo"},
{"the ugly", "il brutto"}
};
// output element with key "the ugly"
std::cout << object.at("the ugly") << '\n';
// change element with key "the bad"
object.at("the bad") = "il cattivo";
// output changed array
std::cout << object << '\n';
// try to write at a nonexisting key
try
{
object.at("the fast") = "il rapido";
}
catch (std::out_of_range& e)
{
std::cout << "out of range: " << e.what() << '\n';
}
}
In case anybody else is still looking for the answer.. You can simply access the contents using the same method as for writing to an nlohmann::json object. For example to get values from
json in the question:
{
"active" : false,
"list1" : ["A", "B", "C"],
"objList" : [
{
"key1" : "value1",
"key2" : [ 0, 1 ]
}
]
}
just do:
nlohmann::json jsonData = nlohmann::json::parse(your_json);
std::cout << jsonData["active"] << std::endl; // returns boolean
std::cout << jsonData["list1"] << std::endl; // returns array
If the "objList" was just an object, you can retrieve its values just by:
std::cout << jsonData["objList"]["key1"] << std::endl; // returns string
std::cout << jsonData["objList"]["key2"] << std::endl; // returns array
But since "objList" is a list of key/value pairs, to access its values use:
for(auto &array : jsonData["objList"]) {
std::cout << array["key1"] << std::endl; // returns string
std::cout << array["key2"] << std::endl; // returns array
}
The loop runs only once considering "objList" is array of size 1.
Hope it helps someone
I really like to use this in C++:
for (auto& el : object["list1"].items())
{
std::cout << el.value() << '\n';
}
It will loop over the the array.
I need some help when iterating over JSON ptree in boost. Here's the structure.
{"drives": [{"busy": false, "eof": false, "density": 88 }]}
What I want to do is to print the key and value eg. busy = false. I've tried the code below but there is no output.
BOOST_FOREACH(ptree::value_type &v, pt.get_child("drives"))
{
cout << v.first << endl; // does not work
cout << v.second.data() << endl; // does not work
cout << v.second.get<string>("busy"); // works
}
So how do I print the key?
Thanks in advance for any help.
I went through some old code and I found the way
BOOST_FOREACH(ptree::value_type &v, pt.get_child("drives"))
{
for(auto iter = v.second.begin(); iter!= v.second.end(); ++iter)
{
std::cout << iter->first << " : " << iter->second.get_value<std::string>() << std::endl;
}
}
You only need to iterate over "drives" if you have more than one "drives", and in your json example you don't have.
In your code you try to print v.first and v.data() but those two doesn't hold the data you think they hold.
v.first supposed to hold the key name of "KeyName":{"busy": false, "eof": false, "density": 88 }
which doesn't exists because this value is part of an array.
the v.data() (If I'm not mistaken) holds the key:value which is an inner presentation and cannot be printed this way.
I really think you should try using a different framework for JSON.
I have the following document in my MongoDB test database:
> db.a.find().pretty()
{
"_id" : ObjectId("5113d680732fb764c4464fdf"),
"x" : [
{
"a" : 1,
"b" : 2
},
{
"a" : 3,
"b" : 4
}
]
}
I'm trying to access and process the elements in the "x" array. However, it seems that the Mongo driver is identifying it not as an array of JSON document, but as Date type, as shown in the following code:
auto_ptr<DBClientCursor> cursor = c.query("test.a", BSONObj());
while (cursor->more()) {
BSONObj r = cursor->next();
cout << r.toString() << std::endl;
}
which output is:
{ _id: ObjectId('51138456732fb764c4464fde'), x: new Date(1360233558334) }
I'm trying to follow the documentation in http://api.mongodb.org/cplusplus and http://docs.mongodb.org/ecosystem/drivers/cpp-bson-array-examples/, but it is quite poor. I have found other examples of processing arrays, but always with simple types (e.g. array of integer), but not when the elements in the array are BSON documents themselves.
Do you have some code example of procesing arrays which elements are generic BSON elements, please?
you could use the .Array() method or the getFieldDotted() method: as in the following:
Query query = Query();
auto_ptr<DBClientCursor> cursor = myConn.query("test.a", query);
while( cursor->more() ) {
BSONObj nextObject = cursor->next();
cout << nextObject["x"].Array()[0]["a"] << endl;
cout << nextObject.getFieldDotted("x.0.a") << endl;
}
At the end, it seems that embeddedObject() method was the key:
auto_ptr<DBClientCursor> cursor = c.query("test.a", BSONObj());
while (cursor->more()) {
BSONObj r = cursor->next();
cout << "Processing JSON document: " << r.toString() << std::endl;
std::vector<BSONElement> be = r.getField("x").Array();
for (unsigned int i = 0; i<be.size(); i++) {
cout << "Processing array element: " << be[i].toString() << std::endl;
cout << " of type: " << be[i].type() << std::endl;
BSONObj bo = be[i].embeddedObject();
cout << "Processing a field: " << bo.getField("a").toString() << std::endl;
cout << "Processing b field: " << bo.getField("b").toString() << std::endl;
}
}
I was wrongly retrieving a different ObjectID and a different type (Date instead of array) becuase I was looking to a different collection :$
Sorry for the noise. I hope that the fragment above helps others to figure out how to manipulate arrays using the MongoDB C++ driver.