I have the following json file
[
{
"a":5855925.424944928,
"b":0,
"c":96,
"d":2096640,
"e":0
}
]
I do this,
boost::property_tree::ptree jsontree;
std::stringstream ss;
ss << "[{\"a\": 5855925.424944928, \"b\": 0, \"c\": 96, \"d\": 2096640, \"e\": 0}]";
boost::property_tree::read_json(ss, jsontree);
// get the children, i.e. the list elements
auto bounds = jsontree.equal_range("");
std::cout << "Size of list : " << std::distance( bounds.first, bounds.second ) << "\n";
But I don't know how to read this from a property tree (eg: get<float>("a"), get<int>("c"))?
Any help would be greatly appreciated.
Thanks
Notice: top-level arrays are not actually supported (you cannot roundtrip that with Boost Property Tree).
The limitations are described in the documentation
Saving this same tree will lose all type information and convert the array to this:
{
"": {
"a": "5855925.424944928",
"b": "0",
"c": "96",
"d": "2096640",
"e": "0"
}
}
Arrays are "objects with empty keys". You already seemed to know that, judging from your sample. So, just use it:
for (auto& object_node : boost::make_iterator_range(jsontree.equal_range(""))) {
ptree const& object = object_node.second;
std::cout << "a: " << object.get<double>("a") << "\n";
std::cout << "b: " << object.get<int>("b") << "\n";
std::cout << "c: " << object.get<int>("c") << "\n";
std::cout << "d: " << object.get<int>("d") << "\n";
std::cout << "e: " << object.get<int>("e") << "\n";
}
Improved Demo
It's often nicer to extract some types/functions:
Live On Coliru
#include <iostream>
#include <boost/property_tree/json_parser.hpp>
using boost::property_tree::ptree;
struct Object {
double a;
int b, c, d, e;
friend std::ostream& operator<<(std::ostream& os, Object const& object) {
return os << "a: " << object.a << "\n"
<< "b: " << object.b << "\n"
<< "c: " << object.c << "\n"
<< "d: " << object.d << "\n"
<< "e: " << object.e << "\n";
}
static Object parse(ptree const& from) {
return {
from.get<double>("a"),
from.get<int>("b"),
from.get<int>("c"),
from.get<int>("d"),
from.get<int>("e"),
};
}
};
int main() {
boost::property_tree::ptree jsontree;
{
std::stringstream ss(R"([{"a": 5855925.424944928, "b": 0, "c": 96, "d": 2096640, "e": 0}])");
boost::property_tree::read_json(ss, jsontree);
}
for (auto& object_node : boost::make_iterator_range(jsontree.equal_range(""))) {
std::cout << Object::parse(object_node.second);
}
}
Prints
a: 5.85593e+06
b: 0
c: 96
d: 2096640
e: 0
You can use BOOST_FOREACH for this. I am attaching some code but they are based on xml_data. But u can use similar to this for getting each value without knowing the key.
BOOST_FOREACH(pt::ptree::value_type &v, tree) {
std::string at = v.first + ATTR_SET;
std::cout << "Extracting attributes from " << at << ":\n";
BOOST_FOREACH(pt::ptree::value_type &v2,v.second.get_child("<xmlattr>")){
std::cout<<""<<v2.first.data()<<" : " <<v2.second.data()<<"\n";
}
std::cout<<"now in book\n";
BOOST_FOREACH(pt::ptree::value_type &v3,tree.get_child("bookstore."+v.first)){
std::cout<<""<<v3.first.data()<<" : " <<v3.second.data()<<"\n";
}
m_modules.insert(v.second.data());
}
here tree is boost::Property_tree::ptree
Related
I'm new to json and trying to use nlohmann library and I'm quite stuck.
config.json file looks like this
{
"Version": 1.1,
"Size": 1024,
"integer": 600,
"Map": [{"0": "india"}, {"1": "usa"}, {"2": "china"}, {"2": "japan"}],
"name": "xxx",
}
I want to get the value of ["Map"]["1"] where "1" is a runtime entity. I have tried several ways but none of them is working.
std::string strRwFilePath = std::string(CONFIG_PATH) + "config.json";
std::ifstream RwFile(strRwFilePath);
if (RwFile.fail())
{
std::cout << "[ReadFileContents]RwFile doesnt exist" << std::endl;
}
else
{
// parsing input
RwFile >> conf_json;
if(!(conf_json.empty()))
{
//METHOD 1
for (auto it = conf_json["Map"].begin(); it != conf_json["Map"].end(); ++it)
{
std::cout << it.key() << " | " << it.value() << "\n";
std::string keyy = std::to_string(m_iRegionType);
std::string tempKey = it.key(); //ERROR- [json.exception.invalid_iterator.207] cannot use key() for non-object iterators
std::cout << "for loop: tempKey:" << tempKey << " \n";
if(!strcmp(tempKey.c_str(),(std::to_string(m_iRegionType)).c_str()))
{
std::cout << "SUCCESS 222" << std::endl;
break;
}
else
{
std::cout << "FAILURE 222" << std::endl;
}
}
//METHOD 2
for(auto& element : conf_json["Map"].items())
{
std::cout << element.key() << " | " << element.value() << "\n";
m_iRegionType = 2;
std::string keyy = std::to_string(m_iRegionType);
std::string tempKey = element.key(); //ERROR: [json.exception.type_error.302] type must be string, but is object
if(!strcmp(tempKey.c_str(),(std::to_string(m_iRegionType)).c_str()))
{
std::cout << "SUCCESS 333" << std::endl;
break;
}
else
{
std::cout << "FAILURE 333" << std::endl;
}
}
//METHOD 3
std::string strTempKey = std::to_string(m_iRegionType);
if(!conf_json["Map"][strTempKey.c_str()].is_null())
{
std::string strName = conf_json["Map"][strTempKey.c_str()]; //ERROR: [json.exception.type_error.305] cannot use operator[] with a string argument with array
std::cout << "key found. RegionName: " << strName << '\n';
}
else
{
std::cout << "key not found" << std::endl;
}
//METHOD 4
// create a JSON object
std::string strKey = "/Map/" + std::to_string(m_iRegionType);
// call find
auto it_two = conf_json.find(strKey.c_str());
if(true == (it_two != conf_json.end()))
{
std::cout << "Region key was found. RegionBucketName: " << *it_two << '\n';
std::string strRegionName = conf_json["Map"][m_iRegionType];
std::string strRegionName2 = *it_two;
std::cout << "strRegionName: " << strRegionName << '\n';
std::cout << "strRegionName2: " << strRegionName2 << '\n';
}
else
{
//getting this as OUTPUT even though key is available
std::cout << "invalid region type, key not available m_iRegionType: " << m_iRegionType << std::endl;
}
}
else
{
std::cout << "[ReadFileContents]Read Write Json object is empty" << std::endl;
}
}
I have also tried using the small json structure where I am not able to access the value using the runtime key.
json j =
{
{"integer", 1},
{"floating", 42.23},
{"string", "hello world"},
{"boolean", true},
{"object", {{"key1", 1}, {"key2", 2}}},
{"array", {1, 2, 3}}
};
int avail4 = j.value("/integer"_json_pointer, 444);
std::cout << "avail4 : " << avail4 << std::endl; //OUTPUT- avial4 : 1
int avail5 = j.value("/object/key2"_json_pointer, 555);
std::cout << "avail5 : " << avail5 << std::endl; //OUTPUT- avial5 : 2
auto strKey3 = "/object/key2";
int avail6 = j.value(strKey3, 666);
std::cout << "avail6 : " << avail6 << std::endl; //OUTPUT- avial6 : 666
Could any one help me.
You can't use ["Map"]["1"] to find the inner array objects. You need iterator through the array
A code example may like this:
#include <nlohmann/json.hpp>
#include <iostream>
// for convenience
using json = nlohmann::json;
int main() {
json j = R"(
{
"Version": 1.1,
"Size": 1024,
"integer": 600,
"Map": [{
"0": "india"
}, {
"1": "usa"
}, {
"2": "china"
}, {
"2": "japan"
}],
"name": "xxx"
}
)"_json;
for (const auto& ele : j["Map"]) {
if (ele.contains("1")) {
std::cout << ele["1"] << std::endl;
}
}
}
Output:
usa
Demo
I have a class that I use with the Armadillo package to create a specific kind of matrix. I'm having trouble debugging it, so I would like to use a function I have written called Matlab_Print. It lives in its own .h and .cpp file and is used throughout my code. The class and the function both work perfectly, but I do not seem to be able to combine them.
I have tried #include "Matlab_Print" in SU3.h both before and after the class definition. I really don't want to make the function a class function as I use Matlab_Print frequently. I do have a workaround but it is inconvenient, and at any rate I am looking at this as a learning opportunity.
I trap error messages with a try when calling the SU3 constructor and I get the following:
error: Mat::init(): size is fixed and hence cannot be changed
main.cpp
#include "pch.h"
#include <new>
#include <exception>
#include "SU3.h"
int main(int argc, char *argv[])
{
int icount { 0 };
SU3 *su3[10];
try
{
for (icount = 0; icount < 10; icount++)
{
su3[icount] = new SU3(0.1);
}
}
catch (int param) { cout << "Function " << __func__ << " int " << param << " exception in memory allocation for su3" << std::endl; exit(1); }
catch (char param) { cout << "Function " << __func__ << " char " << param << " exception in memory allocation for su3" << std::endl; exit(1); }
catch (...) { cout << "Function " << __func__ << " exception in memory allocation for su3" << std::endl; exit(1); }
return 0;
}
SU3.h
#include "pch.h"
#include "SU3.h"
#include <armadillo>
#include "Matlab_Print.h"
class SU3
{
public:
arma::Mat<cx_double>::fixed<3, 3> *X;
SU3(const double epsilon);
};
SU3.cpp
SU3::SU3(const double epsilon) // simplifed so that epsilon plays no role
{
const std::complex<double> o{ 1.0 , 0.0 }; // complex 1
const std::complex<double> z{ 0.0 , 1.0 }; // complex 0
X = new arma::Mat<cx_double>::fixed<3, 3>{ fill::zeros }; //// solution to problem: define and initialize pointer ////
*X = { { o, z, z},
{ z, o, z},
{ z, z, o} };
Matlab_Print(*X, "SU3"); // this is the line I wish to use
}
Matlab_Print.h
#include <armadillo>
#include <complex>
void Matlab_Print(arma::Mat<cx_double>::fixed<3, 3> Matrix, std::string T);
Matlab_Print.cpp
#include "pch.h"
#include "Matlab_Print.h"
void Matlab_Print(arma::Mat<cx_double>::fixed<3, 3> Matrix, std::string T)
{
std::cout << std::endl;
std::cout << "RE = [" << std::real(Matrix(0, 0)) << " " << std::real(Matrix(0, 1)) << " " << std::real(Matrix(0, 2)) << "; ";
std::cout << std::real(Matrix(1, 0)) << " " << std::real(Matrix(1, 1)) << " " << std::real(Matrix(1, 2)) << "; ";
std::cout << std::real(Matrix(2, 0)) << " " << std::real(Matrix(2, 1)) << " " << std::real(Matrix(2, 2)) << "]; " << std::endl;
std::cout << "IM = [" << std::imag(Matrix(0, 0)) << " " << std::imag(Matrix(0, 1)) << " " << std::imag(Matrix(0, 2)) << "; ";
std::cout << std::imag(Matrix(1, 0)) << " " << std::imag(Matrix(1, 1)) << " " << std::imag(Matrix(1, 2)) << "; ";
std::cout << std::imag(Matrix(2, 0)) << " " << std::imag(Matrix(2, 1)) << " " << std::imag(Matrix(2, 2)) << "]; " << std::endl;
std::cout << T << " = RE + 1i*IM;" << std::endl;
}
Thank you for your patience. I hope this is all of the information you need.
As #uneven_mark notes, you have undefined behavior in SU3::SU3, because you are dereferencing X without initializing it first. You probably don't want a pointer here.
N.b. you don't need new to create objects of class type.
class SU3
{
public:
arma::Mat<cx_double>::fixed<3, 3> X;
SU3(const double epsilon);
};
using namespace std::literals::complex_literals;
SU3::SU3(const double epsilon)
: X({ { 1, 1i, 1i },
{ 1i, 1, 1i },
{ 1i, 1i, 1 } }) // prefer member initialisers over assingments
{
Matlab_Print(X, "SU3");
}
I have four classes (A,B,C and D) following the classic diamond pattern and a Container class containing a unique_ptr<A>. I want to serialize these classes using the cereal serialization library.
struct A {int f1; int f2; int f3}
struct B : public virtual A {
template<typename Archive>
inline void save(Archive& ar) const {
std::cerr << "Saving Obj: " << this << std::endl;
std::cerr << "This: " << &(this->f1) << " "
<< &(this->f2) << " " << &(this->f3) << std::endl;
std::cerr << "This: " << this->f1 << " "
<< this->f2 << " " << this->f3 << std::endl;
};
}
};
struct C : public virtual A {};
struct D : public B, public C {};
#include <cereal/archives/binary.hpp>
CEREAL_REGISTER_TYPE(B);
CEREAL_REGISTER_TYPE(C);
CEREAL_REGISTER_TYPE(D);
struct Container {
std::unique_ptr<A> obj;
template<typename Archive>
inline void save(Archive& ar) const {
std::cerr << "Saving Container" << std::endl;
std::cerr << "Obj Addr: " << obj.get() << std::endl;
std::cerr << "Obj: " << &(obj->f1) << " " << &(obj->f2)
<< " " << &(pq->f3) << std::endl;
std::cerr << "Obj: " << " " << pq->sq_count << " " << pq->sq_bits
<< " " << pq->dim << std::endl;
ar(obj); // Call serialization for obj, ie B.save(...)
}
}
All classes have cereal save and load functions, but I only included them for B and Container, as they are the only ones used in this example.
I use these classes as follows :
std::unique_ptr<A> obj(new B);
obj->f1 = 8;
obj->f2 = 8;
obj->f3 = 128;
std::unique_ptr<Container> db(new Container);
db.obj = std::move(obj);
std::ofstream out_file(out_filename);
cereal::BinaryOutputArchive out_archive(out_file);
out_archive(db);
And I get the following output:
Saving Container
Obj Addr: 0x23d2128
Obj: 0x23d2130 0x23d2134 0x23d2138 // Fields adresses (f1,f2,f3)
Obj: 8 8 128 // Fields values
Saving Obj: 0x23d2128 // Same object
This: 0x23d2118 0x23d211c 0x23d2120 // Different field adresses !
This: 4293296 0 37569440 // Garbage
My question is: Is it likely that this is a bug in cereal, or is there something that I don't get with virtual inheritance ?
Is it expected that the addresses of the fields of a given object ever change in a C++ program ?
I can't reproduce your error on the current develop branch of cereal, however I can reproduce it on the current master (1.1.2). I modified your code to actually compile:
#include <cereal/types/memory.hpp>
#include <cereal/types/polymorphic.hpp>
#include <cereal/archives/json.hpp>
#include <fstream>
#include <iostream>
struct A {
int f1; int f2; int f3;
virtual ~A() {}
template<typename Archive>
void serialize( Archive & ar )
{
std::cerr << "Saving A Obj: " << this << std::endl;
std::cerr << "This: " << &(this->f1) << " "
<< &(this->f2) << " " << &(this->f3) << std::endl;
std::cerr << "This: " << this->f1 << " "
<< this->f2 << " " << this->f3 << std::endl;
};
};
struct B : public virtual A {
template <class Archive>
void serialize( Archive & ar )
{
std::cerr << "Saving B Obj: " << this << std::endl;
std::cerr << "This: " << &(this->f1) << " "
<< &(this->f2) << " " << &(this->f3) << std::endl;
std::cerr << "This: " << this->f1 << " "
<< this->f2 << " " << this->f3 << std::endl;
ar( cereal::virtual_base_class<A>( this ) );
}
virtual ~B() {}
};
CEREAL_REGISTER_TYPE(B);
struct Container {
std::unique_ptr<A> obj;
template<typename Archive>
void serialize( Archive & ar )
{
std::cerr << "Saving Container (A)" << std::endl;
std::cerr << "Obj Addr: " << obj.get() << std::endl;
std::cerr << "Obj: " << &(obj->f1) << " " << &(obj->f2)
<< " " << &(obj->f3) << std::endl;
ar(obj); // Call serialization for obj, ie B.save(...)
}
};
int main()
{
std::unique_ptr<A> ptr(new B());
ptr->f1 = 8;
ptr->f2 = 8;
ptr->f3 = 128;
std::unique_ptr<Container> db(new Container());
db->obj = std::move(ptr);
std::stringstream ss;
{
cereal::JSONOutputArchive out_archive(ss);
out_archive(db);
}
std::cout << ss.str() << std::endl;
}
The output with 1.1.2:
Saving Container (A)
Obj Addr: 0x1738d78
Obj: 0x1738d80 0x1738d84 0x1738d88
Saving B Obj: 0x1738d78
This: 0x1738d78 0x1738d7c 0x1738d80
This: 4316664 0 8
Saving A Obj: 0x1738d70
This: 0x1738d78 0x1738d7c 0x1738d80
This: 4316664 0 8
{
"value0": {
"ptr_wrapper": {
"valid": 1,
"data": {
"value0": {
"polymorphic_id": 2147483649,
"polymorphic_name": "B",
"ptr_wrapper": {
"valid": 1,
"data": {
"value0": {}
}
}
}
}
}
}
}
The output using develop:
Saving Container (A)
Obj Addr: 0x1f74e18
Obj: 0x1f74e20 0x1f74e24 0x1f74e28
Saving B Obj: 0x1f74e10
This: 0x1f74e20 0x1f74e24 0x1f74e28
This: 8 8 128
Saving A Obj: 0x1f74e18
This: 0x1f74e20 0x1f74e24 0x1f74e28
This: 8 8 128
{
"value0": {
"ptr_wrapper": {
"valid": 1,
"data": {
"value0": {
"polymorphic_id": 2147483649,
"polymorphic_name": "B",
"ptr_wrapper": {
"valid": 1,
"data": {
"value0": {}
}
}
}
}
}
}
}
So whatever was causing this problem is likely fixed in the current develop branch of cereal, which will be released as 1.2 in the near future.
I've got a question that should be interesting. I'd like to "forward initialize" an item in a std::unordered_map upon construction.
These are the details. I've got a hash map from std::string to a custom class prop, which in my dreams, would initialize a member variable calculating the hash of the string passed to std::unordered_map::operator[].
This is a handy code I've written, but I don't know where to start.
Why this trouble? Because I'd like to avoid something like "if the string is NOT in the container calculate the hash; do stuff with prop". Avoiding this if could be something that might affect my performances. So the constructor, as well as the hashing, will be executed only once, when the map adds a new item in the container. It would be great.
Any hints?
Thanks & Cheers!
#include <iostream>
#include <string>
#include <unordered_map>
class prop
{
public:
prop(std::string s = "") : s_(s), hash_(std::hash<std::string>()(s))
{
// Automagically forwarding the string in the unordered_map...
};
std::string s_;
std::size_t hash_;
int x;
};
int main(int argc, const char * argv[])
{
// Forward the std::string to the prop constructor... but how?
std::unordered_map<std::string, prop> map;
map["ABC"].x = 1;
map["DEF"].x = 2;
map["GHI"].x = 3;
map["GHI"].x = 9; // This should not call the constructor: the hash is there already
std::cout << map["ABC"].x << " : " << map["ABC"].s_ << " : " << map["ABC"].hash_ << std::endl;
std::cout << map["DEF"].x << " : " << map["DEF"].s_ << " : " << map["DEF"].hash_ << std::endl;
std::cout << map["GHI"].x << " : " << map["GHI"].s_ << " : " << map["GHI"].hash_ << std::endl;
std::cout << map["XXX"].x << " : " << map["XXX"].s_ << " : " << map["XXX"].hash_ << std::endl;
return 0;
}
Just use your prop class as a key, instead of string:
#include <iostream>
#include <string>
#include <unordered_map>
class prop
{
public:
prop(std::string s = "") : s_(s), hash_(std::hash<std::string>()(s))
{
// Automagically forwarding the string in the unordered_map...
};
std::string s_;
std::size_t hash_;
};
int main(int argc, const char * argv[])
{
// Forward the std::string to the prop constructor... but how?
std::unordered_map<prop, int, ...> map( ... );
prop pABC( "ABC" ), pDEF( "DEF" ), pGHI( "GHI" );
map[pABC] = 1;
map[pDEF] = 2;
map[pGHI] = 3;
map[pGHI] = 9;
std::cout << map[pABC] << " : " << pABC.s_ << " : " << pABC.hash_ << std::endl;
std::cout << map[pDEF] << " : " << pDEF.s_ << " : " << pDEF.hash_ << std::endl;
std::cout << map[pGHI] << " : " << pGHI.s_ << " : " << pGHI.hash_ << std::endl;
prop pXXX( "XXX" );
std::cout << map[pXXX] << " : " << pXXX.s_ << " : " << pXXX.hash_ << std::endl;
return 0;
}
I omitted custom hash and compare function, the idea should be clear without it.
Is there are a better way than this one to print 2d table?
std::cout
<< std::setw(25) << left << "FF.name"
<< std::setw(25) << left << "BB.name"
<< std::setw(12) << left << "sw.cycles"
<< std::setw(12) << left << "hw.cycles" << "\n"
<< std::setw(25) << left << "------"
<< std::setw(25) << left << "------"
<< std::setw(12) << left << "---------"
<< std::setw(12) << left << "---------" << "\n";
You could put the headers into an array or vector, then generate the correct widths automatically:
boost::array<std::string, 4> head = { ... }
BOOST_FOREACH(std::string& s, head)
{
int w = 5*(s.length()/5 + 1);
std::cout << std::setw(w) << left << s;
}
std::cout << '\n';
BOOST_FOREACH(std::string& s, head)
{
int w = 5*(s.length()/5 + 1);
std::cout << std::string(w,'-');
}
std::cout << std::endl;
Might be worthwhile if you have lots of headers I guess.
Use printf. It's part of C, but it's still supported in C++.
Break things up into functions and it's not so bad.
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
typedef std::vector< std::string > StringVector;
void printRow( std::ostream& s, const StringVector& strings )
{
s << std::setw(25) << std::left << strings[ 0 ];
s << std::setw(25) << std::left << strings[ 1 ];
s << std::setw(12) << std::left << strings[ 2 ];
s << std::setw(12) << std::left << strings[ 3 ];
s << "\n";
}
void printHeadings( std::ostream& s, const StringVector& headings )
{
printRow( s, headings );
StringVector lines;
for ( StringVector::const_iterator H = headings.begin();
H != headings.end();
++H )
{
lines.push_back( std::string( H->size(), '-' ) );
}
printRow( s, lines );
}
int main()
{
StringVector headings( 4 );
headings[ 0 ] = "FF.name";
headings[ 1 ] = "BB.name";
headings[ 2 ] = "sw.cycles";
headings[ 3 ] = "hw.cycles";
printHeadings( std::cout, headings );
StringVector contents( 4 );
contents[ 0 ] = "foo";
contents[ 1 ] = "bar";
contents[ 2 ] = "baz";
contents[ 3 ] = "foobarbaz";
printRow( std::cout, contents );
return 0;
}
Note that I've left out the bounds checking on the string vectors since this is only intended as an example.
Width is the only formatting setting that gets reset, so you can trivially simplify to:
std::cout << left;
std::cout
<< std::setw(25) << "FF.name"
<< std::setw(25) << "BB.name"
<< std::setw(12) << "sw.cycles"
<< std::setw(12) << "hw.cycles"
<< "\n";
You might like:
//...
std::cout << w(25, "FF.name");
//...
// implemented:
template<class T>
struct AtWidth {
std::streamsize width;
T const& obj;
AtWidth(std::streamsize width, T const& obj) : width(width), obj(obj) {}
template<class Stream> // easier than templating on basic_stream
friend Stream& operator<<(Stream& s, AtWidth const& value) {
s.width(value.width);
return s << value.obj;
}
};
template<class T>
AtWidth<T> w(std::streamsize width, T const& obj) {
return AtWidth<T>(width, obj);
}
Or if you want to rename the setw function (C++0x):
auto w(std::streamsize width) -> decltype(std::setw(width)) {
return std::setw(width);
}
// ...
std::cout << w(25) << "FF.name";
(In non-0x, you'd have to either know how your library implements setw to get the right type or re-write it yourself, which isn't too hard, BTW.)
Edit: I missed the second line of dashes here, another answer covers that well enough. The solution for that is indeed to construct a header "object" and print it out more or less at once.