Before answering this question I would request all you good people here to first take a look at this output that I am getting presently. The output is fetched from a sqlite3 table SiteCode which has two columns ID and Code.
Although, I go the output but i still dont see the field name in the output. i mean I need an ouput which looks like the following (name-value pair)
{"ID":"7","Code":"786","ID":"8","Code":"78","ID":"9","Code":"785","ID":"10","Code":"998","ID":"11","Code":"656"}
So do I uses boost-name-value-pair along with parser or do I need to make changes to the existing code ? How ?
My final aim is to send this JSON name-value string over the network using HTTP POST method.
I would highly appreciate if you could guide me through this. If possible could you please point me to some examples ?
Here's how I'd write that loop now:
for (auto &entry : _records) {
ptree obj;
obj.put("ID", entry.id);
obj.put("CODE", entry.code);
pt.insert(pt.end(), { "", obj });
}
Alternative spelling:
pt.push_back(ptree::value_type("", obj));
Edit Of course, if you really want the exact output format from your question, you'd do
for (auto &entry : _records) {
pt.add("ID", entry.id);
pt.add("CODE", entry.code);
}
But I can't see how this format is useful, since you get all kinds of duplicate properties (which are not standard JSON) and rely on the order of properties (which might not be supported by all readers).
With my test again:
$ sqlite3 database.db <<<"create table sitecode(id int primary key, code int);"
$ for a in {1..10}; do echo "insert into sitecode(id,code) values($a, $RANDOM);"; done | sqlite3 database.db
$ ./test
I get:
before loading:
The number of Records is: 0
==============[ AS JSON ]===============
{}
after loading:
The number of Records is: 10
(1,24080) (2,9982) (3,3129) (4,5337) (5,23554) (6,3581) (7,32306) (8,12024) (9,9161) (10,27641)
==============[ AS JSON ]===============
{"":{"ID":"1","CODE":"24080"},"":{"ID":"2","CODE":"9982"},"":{"ID":"3","CODE":"3129"},"":{"ID":"4","CODE":"5337"},"":{"ID":"5","CODE":"23554"},"":{"ID":"6","CODE":"3581"},"":{"ID":"7","CODE":"32306"},"":{"ID":"8","CODE":"12024"},"":{"ID":"9","CODE":"9161"},"":{"ID":"10","CODE":"27641"}}
// 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) {
ptree obj;
obj.put("ID", entry.id);
obj.put("CODE", entry.code);
pt.insert(pt.end(), { "", obj });
}
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 it as a single source