okay, so I am banging my head on this for last couple of days but still I am unable to get it right. I have a std::list container and I want to serialize it into JSON string so that I can send it over network.
NOTE: I compile my code using following:
g++ -std=c++11 -o main main.cpp DBAccess11.cpp -lsqlite3 -lboost_serialization
Below is my DBAccess1.h file.
#ifndef DBAccess1_HH
#define DBAccess1_HH
#include <list> // I have deleted some header for sake of readability
#include <boost/serialization/list.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace std;
using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;
using boost::property_tree::basic_ptree;
//================================//
struct SiteCode
{
int siteID;
int siteCode;
};
inline ostream& operator<< (ostream &out, SiteCode &site)
{
out << "(" << site.siteID << "," << site.siteCode << ")";
return out;
}
//================================//
class sqliteDB {
list<SiteCode> Site_Code_list;
public:
list<SiteCode> GET_ALL_Site_Code();
void printList();
};
#endif**
Below is the DBAccess11.cpp file where all the functions are defined
#include <list> // I have deleted some header for sake of readability
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/serialization/list.hpp>
#include "DBAccess1.h"
using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;
using boost::property_tree::basic_ptree;
list<SiteCode> sqliteDB::GET_ALL_Site_Code()
{
sqlite3 *db;
const char *sql;
sqlite3_stmt * stmt;
int rc = sqlite3_open("/path/to/database.db", &db);
sql = "SELECT * FROM SiteCode;";
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
while(sqlite3_step(stmt)==SQLITE_ROW) {
int A = sqlite3_column_int(stmt, 0);
int B = sqlite3_column_int(stmt, 1);
SiteCode info;
info.siteID = A;
info.siteCode = B;
cout<<"Preparing to push data into List"<<endl;
Site_Code_list.push_back(info);
cout<<"Data was pushed successfully"<<endl;
ptree pt;
for (auto& entry: list<SiteCode> Site_Code_list) //<< ERROR LINE80
pt.put(entry.siteID, entry.siteCode);
std::ostringstream buf;
write_json (buf, pt, false);
cout<< buf.str() << endl;
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return Site_Code_list;
}
//====================================================//
void sqliteDB::printList()
{
int s = Site_Code_list.size();
cout << "The size of List is :" << s << endl;
for( list<SiteCode> :: iterator it = Site_Code_list.begin(); it != Site_Code_list.end(); it++)
cout << *it << " ";
}
Below is main.cpp
#include <list> // I have deleted some header for sake of readability
#include <boost/serialization/list.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
using namespace std;
using boost::property_tree::ptree;
using boost::property_tree::read_json;
using boost::property_tree::write_json;
using boost::property_tree::basic_ptree;
int main()
{
sqliteDB object1;
object1.GET_ALL_Site_Code();
object1.printList();
cout << "\n\nAll the statement were executed properly\n\n";
return 0;
}
The error I get is as follows:
DBAccess11.cpp: In member function ‘std::list<SiteCode> sqliteDB::GET_ALL_Site_Code()’:
DBAccess11.cpp:80:38: error: expected primary-expression before ‘Site_Code_list’
for (auto& entry: list<SiteCode> Site_Code_list)
^
DBAccess11.cpp:80:38: error: expected ‘)’ before ‘Site_Code_list’
DBAccess11.cpp:80:52: error: expected ‘;’ before ‘)’ token
for (auto& entry: list<SiteCode> Site_Code_list)
^
My Questions:
(1)Is this the right way to convert std::list into JSON using boost ? if NO then how should it be done ? (Note- I can only use boost and no other library )
(2) If my approach is right then what changes shall I make to correct it ?
Paths in your tree are always strings. The compiler will tell you this in the remainder of the message. Arguably the documentation is a more readable source:
Both
key_type
anddata_type
are configurable, but will usually bestd::string
here
The
self_type & put(const path_type & path, const Type & value, Translator tr);
So the essence of the fix is
pt.put(std::to_string(entry.id), entry.code);
I got a little bit side-tracked cleaning up the code, so here goes:
Self Contained Sample
// FILE: some header
#include <ostream>
struct SiteCode {
int id;
int code;
SiteCode(int id, int code) : id(id), code(code)
{ }
friend inline std::ostream &operator<<(std::ostream &out, SiteCode const& site) {
return out << "(" << site.id << "," << site.code << ")";
}
};
#include <list> // I have deleted some header for sake of readability
// FILE: sqliteDB header
class sqliteDB {
using Records = std::list<SiteCode>;
Records _records;
public:
void load();
Records const& get() const { return _records; }
void printList() const;
void writeJson(std::ostream& os) const;
};
// FILE: some sqlpp.hpp utility header (inline implementations only)
#include <memory>
#include <sqlite3.h>
namespace sqlpp {
using database = std::shared_ptr<::sqlite3>;
void perror(int rc) {
if (rc != SQLITE_OK) throw std::runtime_error(::sqlite3_errstr(rc));
}
struct statement {
static statement prepare(database db, std::string const& sql) {
::sqlite3_stmt* stmt = nullptr;
perror(::sqlite3_prepare_v2(db.get(), sql.c_str(), -1, &stmt, 0));
return { handle(stmt, ::sqlite3_finalize), db };
}
int step() { return ::sqlite3_step(_stmt.get()); }
int column_int(int c) { return ::sqlite3_column_int(_stmt.get(), c); }
private:
using handle = std::shared_ptr<::sqlite3_stmt>;
database _db; // keeping it around for the lifetime of _stmt
handle _stmt;
statement(handle&& h, database& db) : _db(db), _stmt(std::move(h)) { }
};
database open(char const* path) {
::sqlite3* db = nullptr;
perror(::sqlite3_open(path, &db));
return database(db, ::sqlite3_close);
}
statement prepare(database db, std::string const& sql) {
return statement::prepare(db, sql);
}
}
// FILE: sqliteDB implementation file
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
void sqliteDB::load() {
using namespace sqlpp;
auto stmt = prepare(open("/tmp/database.db"), "SELECT ID, CODE FROM SiteCode;");
while (stmt.step() == SQLITE_ROW)
_records.emplace_back(stmt.column_int(0), stmt.column_int(1));
}
void sqliteDB::writeJson(std::ostream& os) const {
using namespace boost::property_tree;
ptree pt;
for (auto &entry : _records)
pt.put(std::to_string(entry.id), entry.code);
write_json(os, pt, false);
}
// FILE: main program
template <typename List>
static void printList(List const& list) {
int s = list.size();
std::cout << "The number of Records is: " << s << "\n";
for (auto& r : list) std::cout << r << " ";
}
void dump(sqliteDB const& db) {
printList(db.get());
std::cout << "\n==============[ AS JSON ]===============\n";
db.writeJson(std::cout);
}
int main() {
sqliteDB db;
std::cout << "before loading: \n";
dump(db);
std::cout << "after loading: \n";
db.load();
dump(db);
}
Just compile as g++ -std=c++11 -g -Wall -Wextra -pedantic main.cpp -lsqlite3
and get:
sehe@desktop:/tmp$ sqlite3 database.db <<< "create table SiteCode (id int primary key, code int);"
sehe@desktop:/tmp$ for a in {1..10}; do echo "insert into SiteCode(ID,CODE) VALUES($a, $RANDOM);"; done | sqlite3 database.db
sehe@desktop:/tmp$ ./test
Output
before loading:
The number of Records is: 0
==============[ AS JSON ]===============
{}
after loading:
The number of Records is: 10
(1,5591) (2,31578) (3,30641) (4,4850) (5,1628) (6,5133) (7,8798) (8,20601) (9,21213) (10,18222)
==============[ AS JSON ]===============
{"1":"5591","2":"31578","3":"30641","4":"4850","5":"1628","6":"5133","7":"8798","8":"20601","9":"21213","10":"18222"}