c++ 如何使用Boost Describe将包含枚举成员的结构转换为JSON?

qzlgjiam  于 2022-12-15  发布在  其他
关注(0)|答案(1)|浏览(215)

Boost Describe文档中有一个struct自动转换为JSON的例子,但是当添加一个enum(不是嵌套的)作为struct的成员时,代码示例不起作用,我猜需要修改tag_invoke函数才能处理enum。
基于这个例子,我尝试了以下方法:

#include <boost/describe.hpp>
#include <boost/json.hpp>
#include <boost/mp11.hpp>
#include <iostream>
#include <map>
#include <type_traits>
#include <vector>

namespace app {

template <class T,
          class D1 = boost::describe::describe_members<
              T, boost::describe::mod_public | boost::describe::mod_protected>,
          class D2 = boost::describe::describe_members<
              T, boost::describe::mod_private>,
          class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value &&
                                      !std::is_union<T>::value>>

void tag_invoke(boost::json::value_from_tag const &, boost::json::value &v, 
                T const &t) {
  auto &obj = v.emplace_object();

  boost::mp11::mp_for_each<D1>(
      [&](auto D) { obj[D.name] = boost::json::value_from(t.*D.pointer); }); 
}

enum E { e1, e2 };

BOOST_DESCRIBE_ENUM(E, e1, e2);

struct A { 
  int x;
  int y;
  E e;
};

BOOST_DESCRIBE_STRUCT(A, (), (x, y, e)) 

} // namespace app

int main() {
  app::A a{1, 2, app::e1};

  std::cout << boost::json::value_from(a) << std::endl;
}
bzzcjhmw

bzzcjhmw1#

您只为类类型定义了tag_invoke
您需要为枚举类型添加一个:

template <
    class E,
    class = std::enable_if_t<boost::describe::has_describe_enumerators<E>::value>>
void tag_invoke(boost::json::value_from_tag const&, boost::json::value& v, E const& e) {
    auto s = boost::describe::enum_to_string(e, 0);
    v      = s ? s : std::to_string(static_cast<std::underlying_type_t<E>>(e));
}

现在您的示例可以正常工作了:

**一个

#include <boost/core/demangle.hpp>
#include <boost/describe.hpp>
#include <boost/json/src.hpp>
#include <boost/mp11.hpp>
#include <iostream>

namespace app {

    template <
        class E,
        class = std::enable_if_t<boost::describe::has_describe_enumerators<E>::value>>
    void tag_invoke(boost::json::value_from_tag const&, boost::json::value& v, E const& e) {
        auto s = boost::describe::enum_to_string(e, 0);
        v      = s ? s : std::to_string(static_cast<std::underlying_type_t<E>>(e));
    }

    template <
        class T,
        class D1 = boost::describe::describe_members<
            T, boost::describe::mod_public | boost::describe::mod_protected>,          //
        class D2 = boost::describe::describe_members<T, boost::describe::mod_private>, //
        class En = std::enable_if_t<boost::mp11::mp_empty<D2>::value &&
                                    !std::is_union<T>::value> //
        >
    void tag_invoke(boost::json::value_from_tag const&, boost::json::value& v,
                    T const& t) {
        auto& obj = v.emplace_object();

        boost::mp11::mp_for_each<D1>(
            [&](auto D) { obj[D.name] = boost::json::value_from(t.*D.pointer); });
    }

    enum E { e1, e2 };

    struct A {
        int x;
        int y;
        E   e;
    };

    BOOST_DESCRIBE_ENUM(E, e1, e2)
    BOOST_DESCRIBE_STRUCT(A, (), (x, y, e))

} // namespace app

int main() {
    app::A a{1, 2, app::e1};

    std::cout << boost::json::value_from(a) << std::endl;
}

图纸

{"x":1,"y":2,"e":"e1"}

相关问题