不能 get_to 使用 Nlohmann 的 JSON 对象内部的向量
Can't get_to vector of object inside itself with Nlohmann's JSON
我得到了以下代码(简化):
namespace nlohmann {
// https://github.com/nlohmann/json/issues/1749#issuecomment-772996219
template <class T>
void to_json(nlohmann::json &j, const std::optional<T> &v) {
if (v.has_value())
j = *v;
else
j = nullptr;
}
template <class T>
void from_json(const nlohmann::json &j, std::optional<T> &v) {
if (j.is_null())
v = std::nullopt;
else
v = j.get<T>(); /* ERROR LOCATION */
}
} // namespace nlohmann
namespace discordpp{
class Component {
public:
Component(const std::optional<std::vector<Component>> &components)
: components(components) {}
std::optional<std::vector<Component>> components;
// (Resolved) NLOHMANN_DEFINE_TYPE_INTRUSIVE(Component, components)
friend void to_json(nlohmann::json &nlohmann_json_j,
const Component &nlohmann_json_t) {
nlohmann_json_j["components"] = nlohmann_json_t.components;
}
friend void from_json(const nlohmann::json &nlohmann_json_j,
Component &nlohmann_json_t) {
nlohmann_json_j.at("components").get_to(nlohmann_json_t.components); /* ERROR LOCATION */
}
};
}// namespace discordpp
编译returns错误error: no matching function for call to ‘nlohmann::basic_json<>::get<std::vector<discordpp::Component, std::allocator<discordpp::Component> > >() const’
有什么我可以预先声明来解决这个问题的吗?
试过像这样设置 adl_serializer,同样的问题
namespace nlohmann {
template<> struct adl_serializer<discordpp::Component> {
static void to_json(json &nlohmann_json_j, const discordpp::Component &nlohmann_json_t) {
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(
NLOHMANN_JSON_TO, type, custom_id, disabled, style, label, emoji,
url, options, placeholder, min_values, max_values, components))
}
static void from_json(const json &nlohmann_json_j, discordpp::Component &nlohmann_json_t) {
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(
NLOHMANN_JSON_FROM, type, custom_id, disabled, style, label, emoji,
url, options, placeholder, min_values, max_values, components))
}
};
} // namespace nlohmann
我将其更改为共享指针向量,现在我在 adl_serializer
中得到 error: no matching function for call to ‘nlohmann::basic_json<>::get<discordpp::Component>() const’
我写来处理它
template <typename T> struct adl_serializer<std::vector<std::shared_ptr<T>>> {
static void to_json(json &j, const std::vector<std::shared_ptr<T>> &v) {
j = json::array();
for (auto t : v) {
j.push_back(*t);
}
}
static void from_json(const json &j, std::vector<std::shared_ptr<T>> &v) {
if (!j.is_array()) {
throw json::type_error::create(317, "j must be an array", j);
}
for (auto t : j) {
v.push_back(std::make_shared<T>(j.get<T>())); /* Error is here */
}
}
};
镜像于 https://github.com/nlohmann/json/discussions/3047
编辑:
完整源代码(进行递归克隆):https://github.com/DiscordPP/echo-bot/tree/dev-objects
构建失败:https://github.com/DiscordPP/echo-bot/runs/3799394029?check_suite_focus=true
编辑 2:当我这样做时没问题 std::vector<std::shared_ptr<Component>> components;
,它似乎无法处理 2 个第三方解析器,也许吧?
我认为问题在于您在 Component
的向量上调用 get_to
,但您无法将 json
转换为 Component
。
一个解决方案是添加一个构造函数:
explicit Component(const nlohmann::json &nlohmann_json_j = nlohmann::json())
{
// do whatever you have to do
}
请注意,我添加了 = nlohmann::json()
,因为 std::vector<Component>
需要默认构造函数。
注意:我测试了这种方法,它按预期工作。
现场演示:
https://replit.com/@ichramm/somerandomtest
编译:
clang++-7 -Iinclude -std=c++17 -o main main.cpp && ./main
更新:我正在添加更多细节,因为看起来这个问题还没有完全理解。
问题与std::optional
无关。
问题是有一个 组件 的向量,它应该是从 json[=59= 的 向量创建的].
您没有提供 read/write 选项 from/to json 的方法,但您没有提供 read/write 类型 Component
对象的方法。
在j.get<T>();
行中,T
是std::vector<Component>
,而j
可以认为是std::vector<Json>
。
或者,您可以为您的类型 Component
创建一个函数 from_json
。我还没有测试过,但看起来它可能有效。
我认为问题在于您尝试在 class Component
中使用类型为 std::optional<std::vector<Component>>
的成员,而 std::optional
不适用于不完整的类型。将其替换为 std::unique_ptr<std::vector<Component>>
应该可以。
我正在思考@Niels 的回答,我意识到 friend void from_json
正在采用已经构造的 Component&
但 Component
没有默认构造函数。我添加了 Component() : components(std::nullopt) {}
,我们开始比赛了!
我得到了以下代码(简化):
namespace nlohmann {
// https://github.com/nlohmann/json/issues/1749#issuecomment-772996219
template <class T>
void to_json(nlohmann::json &j, const std::optional<T> &v) {
if (v.has_value())
j = *v;
else
j = nullptr;
}
template <class T>
void from_json(const nlohmann::json &j, std::optional<T> &v) {
if (j.is_null())
v = std::nullopt;
else
v = j.get<T>(); /* ERROR LOCATION */
}
} // namespace nlohmann
namespace discordpp{
class Component {
public:
Component(const std::optional<std::vector<Component>> &components)
: components(components) {}
std::optional<std::vector<Component>> components;
// (Resolved) NLOHMANN_DEFINE_TYPE_INTRUSIVE(Component, components)
friend void to_json(nlohmann::json &nlohmann_json_j,
const Component &nlohmann_json_t) {
nlohmann_json_j["components"] = nlohmann_json_t.components;
}
friend void from_json(const nlohmann::json &nlohmann_json_j,
Component &nlohmann_json_t) {
nlohmann_json_j.at("components").get_to(nlohmann_json_t.components); /* ERROR LOCATION */
}
};
}// namespace discordpp
编译returns错误error: no matching function for call to ‘nlohmann::basic_json<>::get<std::vector<discordpp::Component, std::allocator<discordpp::Component> > >() const’
有什么我可以预先声明来解决这个问题的吗?
试过像这样设置 adl_serializer,同样的问题
namespace nlohmann {
template<> struct adl_serializer<discordpp::Component> {
static void to_json(json &nlohmann_json_j, const discordpp::Component &nlohmann_json_t) {
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(
NLOHMANN_JSON_TO, type, custom_id, disabled, style, label, emoji,
url, options, placeholder, min_values, max_values, components))
}
static void from_json(const json &nlohmann_json_j, discordpp::Component &nlohmann_json_t) {
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(
NLOHMANN_JSON_FROM, type, custom_id, disabled, style, label, emoji,
url, options, placeholder, min_values, max_values, components))
}
};
} // namespace nlohmann
我将其更改为共享指针向量,现在我在 adl_serializer
中得到 error: no matching function for call to ‘nlohmann::basic_json<>::get<discordpp::Component>() const’
我写来处理它
template <typename T> struct adl_serializer<std::vector<std::shared_ptr<T>>> {
static void to_json(json &j, const std::vector<std::shared_ptr<T>> &v) {
j = json::array();
for (auto t : v) {
j.push_back(*t);
}
}
static void from_json(const json &j, std::vector<std::shared_ptr<T>> &v) {
if (!j.is_array()) {
throw json::type_error::create(317, "j must be an array", j);
}
for (auto t : j) {
v.push_back(std::make_shared<T>(j.get<T>())); /* Error is here */
}
}
};
镜像于 https://github.com/nlohmann/json/discussions/3047
编辑:
完整源代码(进行递归克隆):https://github.com/DiscordPP/echo-bot/tree/dev-objects
构建失败:https://github.com/DiscordPP/echo-bot/runs/3799394029?check_suite_focus=true
编辑 2:当我这样做时没问题 std::vector<std::shared_ptr<Component>> components;
,它似乎无法处理 2 个第三方解析器,也许吧?
我认为问题在于您在 Component
的向量上调用 get_to
,但您无法将 json
转换为 Component
。
一个解决方案是添加一个构造函数:
explicit Component(const nlohmann::json &nlohmann_json_j = nlohmann::json())
{
// do whatever you have to do
}
请注意,我添加了 = nlohmann::json()
,因为 std::vector<Component>
需要默认构造函数。
注意:我测试了这种方法,它按预期工作。
现场演示:
https://replit.com/@ichramm/somerandomtest
编译:
clang++-7 -Iinclude -std=c++17 -o main main.cpp && ./main
更新:我正在添加更多细节,因为看起来这个问题还没有完全理解。
问题与std::optional
无关。
问题是有一个 组件 的向量,它应该是从 json[=59= 的 向量创建的].
您没有提供 read/write 选项 from/to json 的方法,但您没有提供 read/write 类型 Component
对象的方法。
在j.get<T>();
行中,T
是std::vector<Component>
,而j
可以认为是std::vector<Json>
。
或者,您可以为您的类型 Component
创建一个函数 from_json
。我还没有测试过,但看起来它可能有效。
我认为问题在于您尝试在 class Component
中使用类型为 std::optional<std::vector<Component>>
的成员,而 std::optional
不适用于不完整的类型。将其替换为 std::unique_ptr<std::vector<Component>>
应该可以。
我正在思考@Niels 的回答,我意识到 friend void from_json
正在采用已经构造的 Component&
但 Component
没有默认构造函数。我添加了 Component() : components(std::nullopt) {}
,我们开始比赛了!