首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如果成员变量类型不支持nlohmann的json库,则禁用to_json和from_json

如果成员变量类型不支持nlohmann的json库,则禁用to_json和from_json
EN

Stack Overflow用户
提问于 2022-08-16 21:20:14
回答 2查看 135关注 0票数 0

我正在使用nlohmann的单个标题json库来序列化我编写的类。我想使用这个类与各种类型(包括但不限于boost的多精度类型)。问题是,包括boost的cpp_bin_float_quad在内的某些类型不支持to_json或from_json。

如果我的类的成员变量没有自己的to/from_json,那么该类就无法编译。在这种情况下,用户仍然应该能够使用该类的核心功能(成员函数等),但不能让他们保存/加载类的成员变量。

理想情况下,如果用户需要保存/加载带有自定义类型的类,那么他们可以为其自定义类型创建to/from_json函数。最好的解决方案将适用于C++11。

这里有一个mwe来展示这个问题:

代码语言:javascript
复制
#include "json.hpp"
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <iostream>

template <typename T>
class A {
protected:
  T m_x;
public:
  A() {m_x = static_cast<T>(1);}
  A(T x) : m_x(x) {}

  template <typename T1>
  friend void to_json(nlohmann::json& j, const A<T1>& a);
  template <typename T1>
  friend void from_json(const nlohmann::json& j, A<T1>& a);
};

/* I want useless versions of these two functions
 * if T doesn't have it's own to/from_json functions! */
template <typename T>
void to_json(nlohmann::json& j, const A<T>& a) {
  j = nlohmann::json{{"x", a.m_x}};
}

template <typename T>
void from_json(const nlohmann::json& j, A<T>& a) {
  j.at("x").get_to(a.m_x);
}

// no problems with this MY_TYPE
//#define MY_TYPE double

// fails because cpp_bin_float_quad doesn't have to/from_json
#define MY_TYPE boost::multiprecision::cpp_bin_float_quad

int main(){
  A<MY_TYPE> a(2);
  nlohmann::json js = a;
  std::cout << js << std::endl;
  auto s2 = js.get<A<MY_TYPE>>();
}

当我尝试编译时,我会看到这样的错误:

代码语言:javascript
复制
mwe.cpp:23:5: error: no matching function for call to ‘nlohmann::json_v3_11_0::basic_json<>::basic_json(<brace-enclosed initializer list>)’
   23 |   j = nlohmann::json{{"x", a.m_x}};

mwe.cpp:28:19: error: no matching function for call to ‘nlohmann::json_v3_11_0::basic_json<>::get_to(boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<113, boost::multiprecision::backends::digit_base_2, void, short int, -16382, 16383>, boost::multiprecision::et_off>&) const’
   28 |   j.at("x").get_to(a.m_x);
EN

回答 2

Stack Overflow用户

发布于 2022-08-16 21:33:48

看起来你想让这些朋友函数在没有意义的时候不存在。尝试将函数的签名更改为如下所示

代码语言:javascript
复制
template <typename T>
auto to_json(nlohmann::json& j, const A<T>& a) -> decltype(nlohmann::json{{"x", a.m_x}}, void()) {
  j = nlohmann::json{{"x", a.m_x}};
}
票数 3
EN

Stack Overflow用户

发布于 2022-08-17 00:04:53

看起来我们可以使用SFINAE和std::is_constructible来解决这个问题(只需测试是否可以用它构造json类型)。我为我的mwe使用的具体解决方案是:

代码语言:javascript
复制
template <typename T>
class A {
protected:
  T m_x;
public:
  A() {m_x = static_cast<T>(1);}
  A(T x) : m_x(x) {}

  template <typename T1,
           typename std::enable_if<std::is_constructible<nlohmann::json,T1>::value, bool>::type>
  friend void to_json(nlohmann::json& j, const A<T1>& a);

  template <typename T1,
           typename std::enable_if<std::is_constructible<nlohmann::json,T1>::value, bool>::type>
  friend void from_json(const nlohmann::json& j, A<T1>& a);
};


template <typename T,
         typename std::enable_if<std::is_constructible<nlohmann::json,T>::value, bool>::type = true>
void to_json(nlohmann::json& j, const A<T>& a) {
  j = nlohmann::json{{"x", a.m_x}};
}

template <typename T,
         typename std::enable_if<!std::is_constructible<nlohmann::json,T>::value, bool>::type = true>
void to_json(nlohmann::json& j, const A<T>& a) {
  throw std::invalid_argument(std::string(typeid(T).name()) + " does not implement nlohmann's to_json");
}

template <typename T,
         typename std::enable_if<std::is_constructible<nlohmann::json,T>::value, bool>::type = true>
void from_json(const nlohmann::json& j, A<T>& a){
  j.at("x").get_to(a.m_x);
}

template <typename T,
         typename std::enable_if<!std::is_constructible<nlohmann::json,T>::value, bool>::type = true>
void from_json(const nlohmann::json& j, A<T>& a){
  throw std::invalid_argument(std::string(typeid(T).name()) + " does not implement nlohmann's from_json");
}

编辑:这个解决方案过去依赖于nlohmann::detail::has_from_json<nlohmann::json,T>::value。@在评论中解释了为什么这是个坏主意。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73380469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档