I have nlohmann json object:
json uuid = R"(
{
"uuid": ["aaa","bbb","ccc"]
}
)"_json;
I can get the values in array without problems: str = uuid["uuid"][0];
But how can i get array name himself ?
You can get the underlying map from the json object which gives you the array names and the arrays. If you just want to iterate through the items that's easy as well.
#include <iostream>
#include <json.hpp>
using json = nlohmann::json;
int main()
{
json uuid = R"(
{
"uuid": ["aaa","bbb","ccc"],
"uuie": ["aaa","bbb","ccc"],
"uuif": ["aaa","bbb","ccc"]
}
)"_json;
if (uuid.is_object())
{
auto obj = uuid.get<json::object_t>();
for (auto& kvp : obj)
{
std::cout << kvp.first << ":" << kvp.second << "\n";
}
}
for (auto& item : uuid)
{
std::cout << item << "\n";
}
return 0;
}
Related
I need a function to get the content of a value which need more than one key to access of it.
In the example bellow, I successfully get value of file_content["happy"] but how to write my function get() to accept more than one key for example access to file_content["answer"]["everything"] ?
Note that it could be more than 2 keys.
#include <nlohmann/json.hpp>
#include <string>
#include <fstream>
#include <iostream>
using json = nlohmann::json;
class My_config {
public:
My_config(const std::string config_path) {
// Open and read Configuration file
std::ifstream ifs(config_path);
if (ifs.is_open()) {
file_content = json::parse(ifs);
ifs.close();
}
}
json get(std::string key) {
return file_content[key];
}
private:
json file_content;
};
int main() {
auto my_conf = My_config("../test.json");
std::cout << "Get happy : " << my_conf.get("happy") << std::endl;
// How to get ["answer"]["everything"] ?
std::cout << "Get [answer][everything] : " << my_conf.get("answer", "everything") << std::endl;
return 0;
}
test.json :
{
"answer": {
"everything": 42
},
"happy": true
}
Using a loop should do the job:
json get(std::initializer_list<std::string> keys) {
json data = file_content;
for (auto& key : keys) {
data = data[key];
}
return data;
}
requires extra {} at call site:
my_conf.get({"answer", "everything"});
I have this JSON:
[{"header": "test" , "test2" : "test2"}]
I'm trying to parse this using jsoncpp.
Here's my code snippet:
Json::CharReaderBuilder builder;
Json::CharReader *reader = builder.newCharReader();
Json::Value root;
bool parseRet = reader->parse(serverResponse.c_str(),serverResponse.c_str() +serverResponse.size(), &root, &errors);
parseRet returns true. But root does not include json data.
How do I parse this?
parseRet returns true. But root does not include JSON data.
This sounds like an issue with the way you're accessing the parsed JSON elements.
Below is a complete working example with a raw string literal as JSON input.
A few points:
Use std::unique_ptr for reader to de-allocate memory appropriately at the end. In your code snippet, it's a memory leak.
Read the documentation carefully! Accessing an element using a method or operator might return a default value or an exception so handle accordingly. For example, the JSON in root is an array so it should be accessed by index and then each index contains an object i.e. root[0]["header"].
Example (C++11):
#include <iostream>
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
int main()
{
const std::string raw_json = R"json([{"header": "test" , "test2" : "test2"}])json";
Json::CharReaderBuilder builder {};
// Don't leak memory! Use std::unique_ptr!
auto reader = std::unique_ptr<Json::CharReader>( builder.newCharReader() );
Json::Value root {};
std::string errors {};
const auto is_parsed = reader->parse( raw_json.c_str(),
raw_json.c_str() + raw_json.length(),
&root,
&errors );
if ( !is_parsed )
{
std::cerr << "ERROR: Could not parse! " << errors << '\n';
return -1;
}
std::cout << "Parsed JSON:\n" << root << "\n\n";
try
{
std::cout << "header: " << root[0]["header"] << '\n';
std::cout << "test2 : " << root[0]["test2"] << '\n';
}
catch ( const Json::Exception& e )
{
std::cerr << e.what() << '\n';
}
return 0;
}
Output:
Parsed JSON:
[
{
"header" : "test",
"test2" : "test2"
}
]
header: "test"
test2 : "test2"
I'm new to c++ and trying to use nlohmann library and I'm quite stuck. I want to modify array of objects from json.
json =
{
"a": "xxxx",
"b": [{
"c": "aaa",
"d": [{
"e": "yyy"
},
{
"e": "sss",
"f": "fff"
}
]
}]
}
now I want to replace e value with "example" in the above structure. Could some one help me.
I tried to loop through the json structure and was able to read the "e" value but can't replace it. I tried: `
std::vector<std::string> arr_value;
std::ifstream in("test.json");
json file = json::parse(in);
for (auto& td : file["b"])
for (auto& prop : td["d"])
arr_value.push_back(prop["e"]);
//std::cout<<"prop" <<prop["e"]<< std::endl;
for (const auto& x : arr_value)
std::cout <<"value in vector string= " <<x<< "\n";
for (decltype(arr_value.size()) i = 0; i <= arr_value.size() - 1; i++)
{
std::string s = arr_value[i]+ "emp";
std::cout <<"changed value= " <<s << std::endl;
json js ;
js = file;
std::ofstream out("test.json");
js["e"]= s;
out << std::setw(4) << js << std::endl;
}
The following appends MODIFIED to every "e"-value and writes the result to test_out.json:
#include <vector>
#include <iostream>
#include <fstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main() {
std::ifstream in("test.json");
json file = json::parse(in);
for (auto& td : file["b"])
for (auto& prop : td["d"]) {
prop["e"] = prop["e"].get<std::string>() + std::string(" MODIFIED");
}
std::ofstream out("test_out.json");
out << std::setw(4) << file << std::endl;
}
The prop["e"] = ... line does three things:
It gets the property with key "e",
Coerces it into a string using .get<std::string>() and appends "modified", and
writes back the result to prop["e"], which is a reference to the object nested in the JSON structure.
I have this code that I need to parse/or get the JSON array as std::string to be used in the app.
std::string ss = "{ \"id\" : \"123\", \"number\" : \"456\", \"stuff\" : [{ \"name\" : \"test\" }] }";
ptree pt2;
std::istringstream is(ss);
read_json(is, pt2);
std::string id = pt2.get<std::string>("id");
std::string num= pt2.get<std::string>("number");
std::string stuff = pt2.get<std::string>("stuff");
What is needed is the "stuff" to be retrieved like this as std::string [{ "name" : "test" }]
However the code above stuff is just returning empty string. What could be wrong
Arrays are represented as child nodes with many "" keys:
docs
JSON arrays are mapped to nodes. Each element is a child node with an empty name. If a node has both named and unnamed child nodes, it cannot be mapped to a JSON representation.
Live On Coliru
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using boost::property_tree::ptree;
int main() {
std::string ss = "{ \"id\" : \"123\", \"number\" : \"456\", \"stuff\" : [{ \"name\" : \"test\" }, { \"name\" : \"some\" }, { \"name\" : \"stuffs\" }] }";
ptree pt;
std::istringstream is(ss);
read_json(is, pt);
std::cout << "id: " << pt.get<std::string>("id") << "\n";
std::cout << "number: " << pt.get<std::string>("number") << "\n";
for (auto& e : pt.get_child("stuff")) {
std::cout << "stuff name: " << e.second.get<std::string>("name") << "\n";
}
}
Prints
id: 123
number: 456
stuff name: test
stuff name: some
stuff name: stuffs
Since "stuff" is an array, you can iterate over the elements of it, which are dictionaries. And then you can iterate over the elements of the dictionary, which are key-value pairs:
for (const auto& dict : pt2.get_child("stuff")) {
for (const auto& kv : dict.second) {
std::cout << "key = " << kv.first << std::endl;
std::cout << "val = " << kv.second.get_value<std::string>() << std::endl;
}
}
continue with #sehe 's answer, related to the question asked by #xkm
Is it possible to get it like '[{ "name" : "some" }, { "name" : "stuffs" }]'
Yes, you can. Just treat it with an "unnamed" key which means the key with empty string.
f.g.
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
using boost::property_tree::ptree;
int main()
{
std::stringstream ss;
ss << R"([{"a": 5}, {"a": 9}])";
ptree pt;
read_json(ss, pt);
for (auto& item : pt.get_child(""))
std::cout << "value is " << item.second.get<int>("a") << std::endl;
}
How can I get data from JSON with array as root node by using Boost.PropertyTree?
[
{
"ID": "cc7c3e83-9b94-4fb2-aaa3-9da458c976f7",
"Type": "VM"
}
]
The array elements are just values with a key named "" for property tree:
for (auto& array_element : pt) {
for (auto& property : array_element.second) {
std::cout << property.first << " = " << property.second.get_value<std::string>() << "\n";
}
}
Prints
ID = cc7c3e83-9b94-4fb2-aaa3-9da458c976f7
Type = VM
Live On Coliru
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <iostream>
using namespace boost::property_tree;
int main()
{
std::istringstream iss(R"([
{
"ID": "cc7c3e83-9b94-4fb2-aaa3-9da458c976f7",
"Type": "VM"
}
]
)");
ptree pt;
json_parser::read_json(iss, pt);
for (auto& array_element : pt) {
for (auto& property : array_element.second) {
std::cout << property.first << " = " << property.second.get_value<std::string>() << "\n";
}
}
}