【问题标题】:Serializing std::list into json with boost ptree使用 boost ptree 将 std::list 序列化为 json
【发布时间】:2015-05-28 19:07:20
【问题描述】:

好的,所以过去几天我一直在努力解决这个问题,但我仍然无法做到正确。我有一个 std::list 容器,我想将它序列化为 JSON 字符串,以便我可以通过网络发送它。

注意:我使用以下代码编译我的代码:

g++ -std=c++11 -o main main.cpp DBAccess11.cpp -lsqlite3 -lboost_serialization

我得到了thisthis 的帮助

下面是我的 DBAccess1.h 文件。

#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**

下面是定义所有函数的DBAccess11.cpp文件

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

下面是ma​​in.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;
}

我得到的错误如下:

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)
                                                ^

我的问题:

(1)这是使用 boost 将 std::list 转换为 JSON 的正确方法吗?如果否,那么应该怎么做? (注意-我只能使用 boost 而不能使用其他库)

(2) 如果我的方法是正确的,那么我应该做出哪些改变来纠正它?

【问题讨论】:

  • 应该只用于(自动&条目:Site_Code_list)
  • @ForEveR:我确实已经尝试过了。我收到以下错误。 DBAccess11.cpp:80:40: 错误: 没有匹配函数调用'boost::property_tree::basic_ptree<:basic_string>, std::basic_string >::add(int&, int&)' pt.add(entry.siteID, entry.siteCode);

标签: c++ json serialization boost boost-propertytree


【解决方案1】:

树中的路径始终是字符串。编译器将在消息的其余部分中告诉您这一点。可以说文档是一个更具可读性的来源:

key_typedata_type 都是可配置的,但通常是 std::string here

self_type &amp; put(const path_type &amp; path, const Type &amp; value, Translator tr);

所以修复的本质是

pt.put(std::to_string(entry.id), entry.code);

我在清理代码时有点偏题,所以这里是:

自包含样本

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

只需编译为g++ -std=c++11 -g -Wall -Wextra -pedantic main.cpp -lsqlite3 并得到:

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

输出

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

【讨论】:

  • 哇。有很多东西要我去吸收。我会尽快回复您。非常感谢您抽出时间回复。
  • 附言。我提到的主要元素是:对象生命周期、异常安全和使用 RAII 的 DRY(主要是 shared_ptr 技巧);命令/查询分离;常量正确性;适当的命名; (代码的模块化)
  • 我希望我能给你 1000 票。你的回答完美无缺。我根据需要修改了您的答案并获得了预期的结果。明天我将在此页面上发布我的答案。我也有一些后续问题。
【解决方案2】:

好的,所以正在研究 sehe 提供的上述解决方案。我终于能够得到正确的输出。我不得不根据我的需要修改他的解决方案。这里的答案如下。感谢 sehe。

下面是我的 DBAccess1.h 文件:

#ifndef DBAccess1_HH
#define DBAccess1_HH

#include <sqlite3.h>
#include <list>   
#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;

    friend inline std::ostream &operator<<(std::ostream &out, SiteCode const& site) {
    return out << "(" << site.siteID << "," << site.siteCode << ")";
    }
};
//=========================//
class sqliteDB {

using Records = std::list<SiteCode>;
Records Site_Code_list;

public:

list<SiteCode> GET_ALL_Site_Code();
Records const& get() const { return Site_Code_list; }
void writeJson(std::ostream& os) const;
void printList() const;
};

#endif

下面是DBAccess11.cpp

#include <ostream>
#include <boost/serialization/list.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.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;
    }
    sqlite3_finalize(stmt);
    sqlite3_close(db);
    return Site_Code_list;
}
//==============================================================//
void sqliteDB::writeJson(std::ostream& os) const
{
    using namespace boost::property_tree;
    ptree pt;

    for (auto &entry : Site_Code_list)
        pt.put(std::to_string(entry.siteID), entry.siteCode);

    write_json(os, pt, false);
}
//=========================================================//

下面是ma​​in.cpp

#include <ostream>

#include <boost/serialization/list.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

#include "DBAccess1.h"

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;

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 object1;

    std::cout << "before loading: \n";
    dump(object1);

    std::cout << "after loading: \n";
    object1.GET_ALL_Site_Code();
    dump(object1);

    return 0;
}

编译以上使用:

g++ -std=c++11 -o main main.cpp DBAccess11.cpp -lsqlite3 -lboost_serialization 

以下是我得到的输出

before loading: 
The number of Records is: 0

==============[ AS JSON ]===============
{}
after loading: 
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
Preparing to push data into List
Data was pushed successfully
The number of Records is: 10
(7,786) (8,78) (9,785) (10,998) (11,656) (13,23) (14,7) (15,74) (16,954) (17,752) 
==============[ AS JSON ]===============
{"7":"786","8":"78","9":"785","10":"998","11":"656","13":"23","14":"7","15":"74","16":"954","17":"752"}

【讨论】:

    猜你喜欢
    • 2023-04-06
    • 2015-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多