1

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 ?

Community
  • 1
  • 1
K.K
  • 401
  • 5
  • 22
  • Hehehe. I never realized you wanted the field names there. Good examples of the expected output go a long way in your question! Hold on. Posting in a minute – sehe Mar 26 '15 at 12:17
  • @sehe haha...sehe could you please point me to some resources where I can get to read about it. I tried to google alot about this. But almost all the example are based on XML. I tried to get it done based on those XML examples but it did not work out. I really need to learn about the basics of this stuff.:/ – K.K Mar 26 '15 at 12:22
  • I'd suggest google, [boost property tree json array](http://bit.ly/1FWDbSY) leads me to [Creating JSON arrays in Boost using Property Trees](http://stackoverflow.com/questions/2114466/creating-json-arrays-in-boost-using-property-trees) and the [Boost docs](http://www.boost.org/doc/libs/1_57_0/doc/html/boost_propertytree/parsers.html#boost_propertytree.parsers.json_parser) aysing _"JSON arrays are mapped to nodes. Each element is a child node with an empty name."_ – sehe Mar 26 '15 at 12:34

1 Answers1

1

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"}}

Full Demo

// 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

sehe
  • 374,641
  • 47
  • 450
  • 633
  • whoa, man you knowledge regarding boost & JSON seems phenomenal. I am so super impressed. – K.K Mar 26 '15 at 12:35
  • In one of my experiments with of merging your code with mine, I tried putting following in my GET_ALL_SiteCode(). But it showed me error that "reference variable std::ostream& os is uninitialised" why ? ptree pt; std::ostream& os; for (auto &entry : Site_Code_list) pt.put(std::to_string(entry.siteID), entry.siteCode); write_json(os, pt, false); – K.K Mar 26 '15 at 12:38
  • Because you don't initialize `os`. Which is a reference variable. – sehe Mar 26 '15 at 12:44