I got a little problem.
My json looks like this:
{
"data" :
{
"Money" :
{
"testUser3" : "500",
"testUser2" : "23",
"testUser1" : "2435",
"testUser" : "60"
}
}}
And I am trying to get the value + names of all the users.. but I don't know how, because the user names can change I can't use root["data"]["Money"]["testUser"].asInt();
I hope someone can help me, thanks.
you were downvoted, but I'll help you anyway, cause I need something similar.. let's thank Brandon in JsonCpp - when having a json::Value object, how can i know it's key name? for the keys part..
#include <string>
#include <iostream>
#include "jsoncpp-master/include/json/value.h"
#include "jsoncpp-master/include/json/json.h"
using namespace std;
bool Testjson2()
{
string s =
" { \"data\" :{"
" \"Money\" : {"
" \"testUser3\" : \"500\","
" \"testUser2\" : \"23\","
" \"testUser1\" : \"2435\","
" \"testUser\" : \"60\""
" }"
" } }";
Json::Value root;
Json::Reader reader;
string sdress = "{\"\":[" + s + "]}";
if (!reader.parse(sdress, root))
{
cout << sdress << "\n" << "Parse error\n";
return false;
}
const Json::Value datasections = root[""];
Json::Value v = datasections [0]["data"]["Money"];
cout << "There are " << v.size() << " members\n";
for (auto const& id : v.getMemberNames())
cout << id << " has " << v[id] << std::endl;
return true;
}
Related
I wanto to use sscanf to extrat the 2 first integer (5 and 10) in a string
rssi = 5
ber = 10
like this :
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
int main() {
std::string str = "\r\n+CSQ: 5,10\r\n\r\nOK\r\n7556\r\n";
unsigned char lBufRX[100];
char *rssi, *ber;
if((sscanf(str.c_str(), "%*[^:]: %s,%s[^\n]", rssi, ber)) != 2) {
std::cout <<"[" << rssi << "]" << "[" << ber << "]" << std::endl;
}
return 0;
}
The result is bad. Can anyone help me ?
My output is : "[5,10][" with " %*[^:]: " i read until the first integer so "5" with ",%s[^\n]" i read the second integer so "10" until \r\n
Thanks
You have several errors. You're using char* although you want to read two ints. But then you don't allocate memory for them. Also, you're expecting two successful parses but check with != 2. Here is some code that works:
int main() {
std::string str = "\r\n+CSQ: 5,10\r\n\r\nOK\r\n7556\r\n";
int rssi, ber;
if((sscanf(str.c_str(), "%*[^:]: %d,%d", &rssi, &ber)) == 2) {
std::cout <<"[" << rssi << "]" << "[" << ber << "]" << std::endl;
}
return 0;
}
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 can't show you all the code, 'cause it is large but I can show example of the stuff that I'm trying to use. So, code is the following:
namespace TestNamespace {
struct TestBase
{
TestBase(std::string _id = "") : id(_id) {}
std::string id;
};
struct Test : public TestBase
{
Test(std::string _id = "") : TestBase(_id), b1(true), b2(true) {}
bool b1;
bool b2;
};
typedef std::list<Test> Tests;
struct SomeStatesHolder
{
SomeStatesHolder() : tests(), someAdditionalVar(true), someAdditionVar2(2222) {}
Tests tests;
bool someAdditionalVar;
int someAdditionVar2;
};
}
class WorkingClass
{
public:
WorkingClass() : m_someStatesHolder(new TestNamespace::SomeStatesHolder()) {
TestNamespace::Test t("id1");
m_someStatesHolder->tests.push_back(t);
}
TestNamespace::Tests getTests() const { return m_someStatesHolder->tests; }
bool getB1(const std::string& id) const {
const auto fnd = std::find_if(m_someStatesHolder->tests.cbegin(), m_someStatesHolder->tests.cend(), [&](const TestNamespace::Test& t){
return t.id == id;
});
return (fnd == m_someStatesHolder->tests.cend()) ? true : fnd->b1;
}
bool getB2(const std::string& id) const {
const auto fnd = std::find_if(m_someStatesHolder->tests.cbegin(), m_someStatesHolder->tests.cend(), [&](const TestNamespace::Test& t){
return t.id == id;
});
return (fnd == m_someStatesHolder->tests.cend()) ? true : fnd->b2;
}
private:
TestNamespace::SomeStatesHolder *m_someStatesHolder;
};
But deep in the project in function of yet another class I have lines:
qDebug() << "\n\n\n\nTESTS: "
<< workingClass.getB1("id1") << ":" << !workingClass.getB1("id1") << " "
<< workingClass.getB2("id1") << ":" << !workingClass.getB2("id1");
const auto tests = workingClass.getTests();
const std::string fid = "id1";
const auto fnd = std::find_if(tests.cbegin(), tests.cend(), [&](const TestNamespace::Test& t){
return t.id == fid;
});
qDebug() << "\nTESTS2: "
<< fnd->b1 << ":" << !fnd->b1 << " "
<< fnd->b2 << ":" << !fnd->b2;
And the output of that lines is:
TESTS: true : true true : true
TESTS2: true : true true : true
What could be the reason of such a strange behaviour? Why ! didn't work? I should admit, that
this stranges are in Linux, OSX. In Windows everything is fine
new similar test stuff works fine (like this), but my particular struct in project - not.
UPD1: I also tried to make functions for getting those values, result the same. Code like this also not working:
qDebug() << "Test3: "
<< workingClass.getB1("id1") << ":"
<< !((bool)workingClass.getB1("id1")) << ":"
<< !workingClass.getB1("id1") << ":"
<< (!(workingClass.getB1("id1")))
bool AAAAA = workingClass.getB1("id1");
qDebug() << "Test4: "
<< AAAAA << ":"
<< !((bool)AAAAA)) << ":"
<< !AAAAA << ":"
<< (!(AAAAA))
std::find_if will return last if nothing is found, which points after the last element std::list. That is memory garbage, that you are returning with return fnd->b1.
When you negate this memory garbage, the last bit will be negated, thus you end up with 112 : 113 58 : 59 when casting it to int.
I found a problem. In my project in a same class (SomeStatesHolder) my bool values wasn't initialized in constructor list.
ps: use damn -Wreorder or even better -Werror -Wall
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;
}
I have to write an XML parser with Boost. However I have some trouble.
I can access the nodes name without any problem, but for some reason I can't access the attributes inside a tag by using get_value, which should work instantly. Maybe there is a mistake in my code I didn't spot? Take a look:
void ParametersGroup::load(const boost::property_tree::ptree &pt)
{
using boost::property_tree::ptree;
BOOST_FOREACH(const ptree::value_type& v, pt)
{
name = v.second.get_value<std::string>("name");
std::string node_name = v.first;
if (node_name == "<xmlattr>" || node_name == "<xmlcomment>")
continue;
else if (node_name == "ParametersGroup")
sg.load(v.second); // Recursion to go deeper
else if (node_name == "Parameter")
{
// Do stuff
std::cout << "PARAMETER_ELEM" << std::endl;
std::cout << "name: " << name << std::endl;
std::cout << "node_name: " << node_name << std::endl << std::endl;
}
else
{
std::cerr << "FATAL ERROR: XML document contains a non-recognized element: " << node_name << std::endl;
exit(-1);
}
}
}
So basically I ignore and tags, when I'm in a ParametersGroup tag I go deeper, and when I'm in a Parameter tag I recover the datas to do stuff. However, I can't get the "name" properly.
This is the kind of lines I'm scanning in the last else if :
<Parameter name="box">
The std::cout << name displays things like that:
name: ^M
^M
^M
^M
^M
^M
which is obvisouly not what I'm asking for.
What am I doing wrong? Any help would be greatly appreciated.
Since your question isn't particularly selfcontained, here's my selfcontained counter example:
Live On Coliru
#include <sstream>
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
using namespace boost::property_tree;
int main() {
ptree pt;
std::istringstream iss("<Parameter name=\"box\" />");
xml_parser::read_xml(iss, pt);
for (auto& element : pt)
{
std::cout << "'" << element.first << "'\n";
for (auto& attr : element.second)
{
std::cout << "'" << attr.first << "'\n";
for (auto& which : attr.second)
{
std::cout << "'" << which.first << "': \"" << which.second.get_value<std::string>() << "\"\n";
}
}
}
}
It prints
'Parameter'
'<xmlattr>'
'name': "box"
I hope you can see what you need to do (likely an unexpected level of nodes in the tree?). To get directly to the leaf node:
pt.get_child("Parameter.<xmlattr>.name").get_value<std::string>()