c++ - Boost 将对象序列化为 json

标签 c++ json serialization boost

假设我有一个类型为 Animal 的对象,我将其序列化。

在下面的例子中,要序列化的内容是

22 serialization::archive 16 0 0 4 1 5 Horse

不错。但是,如果我需要将它序列化为 json 怎么办。是否可以通过 boost 序列化?

我要找这样一个字符串:

{
  "legs": 4,
  "is_mammal": true,
  "name": "Horse"
}

代码:

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <iostream>
#include <sstream>

using namespace boost::archive;

class Animal
{
public:
    Animal(){}
    void set_leg(int l){legs=l;};
    void set_name(std::string s){name=s;};
    void set_ismammal(bool b){is_mammal=b;};
    void print();

private:
    friend class boost::serialization::access;

    template <typename Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & legs;
        ar & is_mammal;
        ar & name;
    }

    int legs;
    bool is_mammal;
    std::string name;
};

void Animal::print()
{
    std::cout
        <<name<<" with "
        <<legs<<" legs is "
        <<(is_mammal?"":"not ")
        <<"a mammal"<<std::endl;
}

void save_obj(const Animal &animal,std::stringstream &stream)
{
    text_oarchive oa{stream};
    oa << animal;
}

void load_obj(std::stringstream &stream,Animal &animal)
{
  text_iarchive ia{stream};
  ia >> animal;
}

int main()
{
    std::stringstream stream;
    Animal animal;
    animal.set_name("Horse");
    animal.set_leg(4);
    animal.set_ismammal(true);
    save_obj(animal,stream);
    Animal duplicate;
    load_obj(stream,duplicate);
    std::cout<<"object print: ";
    duplicate.print();
    std::cout<<"stream print: "<<stream.str()<<std::endl;
}

// g++ -std=c++11 main.cpp -lboost_serialization && ./a.out

结果

object print: Horse with 4 legs is a mammal
stream print: 22 serialization::archive 16 0 0 4 1 5 Horse

最佳答案

不,没有这样的事情。

您可以编写自己的(通过实现存档概念)。但我认为这不值得付出努力。只需使用 JSON 库即可。

这是适用于您的示例的最小输出存档模型的草图:

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <iostream>
#include <iomanip>
#include <sstream>

struct MyOArchive {
    std::ostream& _os;
    MyOArchive(std::ostream& os) : _os(os) {}
    using is_saving = boost::true_type;

    template <typename T>
        MyOArchive& operator<<(boost::serialization::nvp<T> const& wrap) {
            save(wrap.name(), wrap.value());
            return *this;
        }

    template <typename T>
        MyOArchive& operator<<(T const& value) {
            return operator<<(const_cast<T&>(value));
        }

    template <typename T>
        MyOArchive& operator<<(T& value) {
            save(value);
            return *this;
        }

    template <typename T> MyOArchive& operator&(T const& v) { return operator<<(v); }

    bool first_element = true;
    void start_property(char const* name) {
        if (!first_element) _os << ", ";
        first_element = false;
        _os << std::quoted(name) << ":";
    }
    template <typename T> void save(char const* name, T& b) {
        start_property(name);
        save(b);
    }
    void save(bool b) { _os << std::boolalpha << b; }
    void save(int i) { _os << i; }
    void save(std::string& s) { _os << std::quoted(s); }

    template <typename T>
    void save(T& v) {
        using boost::serialization::serialize;
        _os << "{";
        first_element = true;
        serialize(*this, v, 0u);
        _os << "}\n";
        first_element = false;
    }
};

class Animal {
  public:
    Animal() {}
    void set_leg(int l) { legs = l; };
    void set_name(std::string s) { name = s; };
    void set_ismammal(bool b) { is_mammal = b; };
    void print();

  private:
    friend class boost::serialization::access;

    template <typename Archive> void serialize(Archive &ar, unsigned) 
    {
        ar & BOOST_SERIALIZATION_NVP(legs)
           & BOOST_SERIALIZATION_NVP(is_mammal)
           & BOOST_SERIALIZATION_NVP(name);
    }

    int legs;
    bool is_mammal;
    std::string name;
};

void Animal::print() {
    std::cout << name << " with " << legs << " legs is " << (is_mammal ? "" : "not ") << "a mammal" << std::endl;
}

void save_obj(const Animal &animal, std::stringstream &stream) {
    MyOArchive oa{ stream };
    oa << animal;
}

int main() {
    std::stringstream stream;
    {
        Animal animal;
        animal.set_name("Horse");
        animal.set_leg(4);
        animal.set_ismammal(true);

        save_obj(animal, stream);
    }

    std::cout << "stream print: " << stream.str() << std::endl;
}

打印

stream print: {"legs":4, "is_mammal":true, "name":"Horse"}

CAVEAT

I do not recommend this approach. In fact there are numerous missing things in the above - most notably the fact that it is output-only

关于c++ - Boost 将对象序列化为 json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48702355/

相关文章:

javascript - 将 JSON 中的大数字解析为字符串

c# - 自定义集合属性未序列化

java - 如何将 Java ZonedDateTime 序列化为 XML 文件

java - 使用 Jackson 反序列化 Java 数组

c# - 发送列表时的 '`'字符和RestSharp请求体

c++ - move 赋值运算符 C++

c++ - CMake:包含 vs add_subdirectory:相对头文件路径

c++ - 使编译器不自动刷新缓冲区

c++ - 停靠区分隔符的Qt样式表

json - 解码 Json Swift 4 Codable Type Any