I have a structure which has an explicit constructor -
struct structA {
explicit structA(const std::size_t num) : a(num) {}
std::vector<structB> a;
glm::quat b;
glm::vec3 c;
glm::vec3 d{1.0f};
};
I have a to_json
and from_json
for structA
as below -
inline void to_json(json& j, const structA& t) {
j = {{"a", t.a},
{"b", t.b},
{"c", t.c},
{"d", t.d}};
}
inline void from_json(const json& j, structA& t) {
j.at("a").get_to(t.a);
j.at("b").get_to(t.b);
j.at("c").get_to(t.c);
j.at("d").get_to(t.d);
}
to_json() works fine and the json file is filled properly.
note - I have to and from json for structB
as well and structB doesnt have an exlipcit constructor and is working as expected
When I try to read the structA values from the json as below, I pass in the value 21
as arg since the explicit constructor needs an input value.
const auto& structAVal = frameJson["structA"].get<structA>(21);
But I get a compile error as -
include/nlohmann_json/nlohmann/json.hpp:19336:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided
basic_json get() const
include/nlohmann_json/nlohmann/json.hpp:19336:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided
BasicJsonType get() const
include/nlohmann_json/nlohmann/json.hpp:19336:16: note: candidate function template not viable: requires 0 arguments, but 1 was provided
ValueType get() const noexcept(noexcept(
Question - Where am I going wrong here ? The error above looks like from_json()
needs another input arg ??
If I dont provide the input arg 21
in the constructor arg while reading the json, I get a bunch of errors on the lines of
1 argument expected, 0 provided
So it is a cyclic loop
https://github.com/nlohmann/json#basic-usage
"When using template get<your_type>(), your_type MUST be DefaultConstructible. (There is a way to bypass this requirement described later.)"
https://github.com/nlohmann/json#how-can-i-use-get-for-non-default-constructiblenon-copyable-types
There is a way, if your type is MoveConstructible. You will need to specialize the adl_serializer as well, but with a special from_json overload:
So I think your answer lies in this idea. (Following code untested and probably doesn't compile)
namespace nlohmann {
template <>
struct adl_serializer< structA> {
// note: the return type is no longer 'void', and the method only takes
// one argument
static structA from_json(const json& j) {
std::size_t num;
j.at("a").get_to(num);
structA t{a};
j.at("b").get_to(t.b);
j.at("c").get_to(t.c);
j.at("d").get_to(t.d);
return t;
}
// Here's the catch! You must provide a to_json method! Otherwise, you
// will not be able to convert move_only_type to json, since you fully
// specialized adl_serializer on that type
static void to_json(json& j, structA t) {
j = {{"a", t.a},
{"b", t.b},
{"c", t.c},
{"d", t.d}};
}
};
}