有两种解决方案。
手动操作
您可以提供一个接受json::value 并返回您类型的对象的函数:
User fromJson(json::value data) {
return User{data[U("username")].as_string(), data[U("info")].as_string()};
}
自动执行
C++ 中没有反射。真的。但是如果编译器不能为你提供元数据,你可以自己提供。
让我们从创建一个属性结构开始:
template<typename Class, typename T>
struct Property {
constexpr Property(T Class::*aMember, const char* aName) : member{aMember}, name{aName} {}
using Type = T;
T Class::*member;
const char* name;
};
好的,现在我们有了编译时自省系统的构建块。
现在在您的班级用户中,添加您的元数据:
struct User {
constexpr static auto properties = std::make_tuple(
Property<User, std::string>{&User::username, "username"},
Property<User, std::string>{&User::info, "info"}
);
private:
std::string username;
std::string info;
};
现在您有了所需的元数据,您可以通过递归来遍历它:
template<std::size_t iteration, typename T>
void doSetData(T&& object, const json::value& data) {
// get the property
constexpr auto property = std::get<iteration>(std::decay_t<T>::properties);
// get the type of the property
using Type = typename decltype(property)::Type;
// set the value to the member
object.*(property.member) = asAny<Type>(data[U(property.name)]);
}
template<std::size_t iteration, typename T, typename = std::enable_if_t<(iteration > 0)>>
void setData(T&& object, const json::value& data) {
doSetData<iteration>(object, data);
// next iteration
setData<iteration - 1>(object, data);
}
template<std::size_t iteration, typename T, typename = std::enable_if_t<(iteration == 0)>>
void setData(T&& object, const json::value& data) {
doSetData<iteration>(object, data);
}
template<typename T>
T fromJson(Json::Value data) {
T object;
setData<std::tuple_size<decltype(T::properties)>::value - 1>(object, data);
return object;
}
这样就可以了。
我没有测试这段代码,所以如果你有问题,请在 cmets 中告诉我。
请注意,您需要编写asAny 函数。它只是一个接受 Json::Value 并调用正确的 as_... 函数或另一个 fromJson 的函数;)