使用 JSON boost 序列化创建 JSON 字符串时如何获取名称-值对?

how get name-value pair when creating JSON string from using JSON boost serialization?

在回答这个问题之前,我想请各位好心人先看看我目前得到的 输出。输出是从 sqlite3 table SiteCode 中获取的,它有两列 IDCode .

虽然,我去了输出,但我仍然没有在输出中看到字段名称。 我的意思是我需要一个如下所示的输出(名称-值对)

{"ID":"7","Code":"786","ID":"8","Code":"78","ID":"9","Code":"785","ID":"10","Code":"998","ID":"11","Code":"656"}

那么我是将 boost-name-value-pair 与解析器一起使用,还是需要对现有代码进行更改?怎么样?

我的最终目标是使用 HTTP POST 方法通过网络发送此 JSON 名称-值字符串。

如果你能指导我解决这个问题,我将不胜感激。如果可能的话,你能给我举一些例子吗?

下面是我现在编写该循环的方式:

for (auto &entry : _records) {
    ptree obj;
    obj.put("ID", entry.id);
    obj.put("CODE", entry.code);
    pt.insert(pt.end(), { "", obj });
}

替代拼写:

    pt.push_back(ptree::value_type("", obj));

编辑 当然,如果您真的想要您问题的确切输出格式, 你会做

for (auto &entry : _records) {
    pt.add("ID", entry.id);
    pt.add("CODE", entry.code);
}

但我看不出这种格式有什么用,因为您会得到各种重复的属性(这不是标准的 JSON)并且依赖于属性的顺序(可能不支持所有读者)。

又是我的测试:

$ 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

我得到:

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);
}

只需将其编译为单一源代码