22
33#include " behaviortree_cpp/basic_types.h"
44#include " behaviortree_cpp/utils/safe_any.hpp"
5- #include " behaviortree_cpp/contrib/expected.hpp "
5+ #include " behaviortree_cpp/basic_types.h "
66
77// Use the version nlohmann::json embedded in BT.CPP
88#include " behaviortree_cpp/contrib/json.hpp"
@@ -73,14 +73,32 @@ class JsonExporter
7373 */
7474 ExpectedEntry fromJson (const nlohmann::json& source) const ;
7575
76- // / Same as the other, but providing the specific type
76+ // / Same as the other, but providing the specific type,
77+ // / To be preferred if the JSON doesn't contain the field [__type]
7778 ExpectedEntry fromJson (const nlohmann::json& source, std::type_index type) const ;
7879
80+ template <typename T>
81+ Expected<T> fromJson (const nlohmann::json& source) const ;
82+
7983 // / Register new JSON converters with addConverter<Foo>().
8084 // / You should have used first the macro BT_JSON_CONVERTER
8185 template <typename T>
8286 void addConverter ();
8387
88+ /* *
89+ * @brief addConverter register a to_json function that converts a json to a type T.
90+ *
91+ * @param to_json the function with signature void(const T&, nlohmann::json&)
92+ * @param add_type if true, add a field called [__type] with the name ofthe type.
93+ * */
94+ template <typename T>
95+ void addConverter (std::function<void (const T&, nlohmann::json&)> to_json,
96+ bool add_type = true);
97+
98+ // / Register custom from_json converter directly.
99+ template <typename T>
100+ void addConverter (std::function<void (const nlohmann::json&, T&)> from_json);
101+
84102private:
85103 using ToJonConverter = std::function<void (const BT::Any&, nlohmann::json&)>;
86104 using FromJonConverter = std::function<Entry(const nlohmann::json&)>;
@@ -90,6 +108,22 @@ class JsonExporter
90108 std::unordered_map<std::string, BT::TypeInfo> type_names_;
91109};
92110
111+ template <typename T>
112+ inline Expected<T> JsonExporter::fromJson (const nlohmann::json& source) const
113+ {
114+ auto res = fromJson (source);
115+ if (!res)
116+ {
117+ return nonstd::expected_lite::make_unexpected (res.error ());
118+ }
119+ auto casted = res->first .tryCast <T>();
120+ if (!casted)
121+ {
122+ return nonstd::expected_lite::make_unexpected (casted.error ());
123+ }
124+ return *casted;
125+ }
126+
93127// -------------------------------------------------------------------
94128
95129template <typename T>
@@ -117,6 +151,33 @@ inline void JsonExporter::addConverter()
117151 from_json_converters_.insert ({ typeid (T), from_converter });
118152}
119153
154+ template <typename T>
155+ inline void JsonExporter::addConverter (
156+ std::function<void (const T&, nlohmann::json&)> func, bool add_type)
157+ {
158+ auto converter = [func, add_type](const BT::Any& entry, nlohmann::json& json) {
159+ func (entry.cast <T>(), json);
160+ if (add_type)
161+ {
162+ json[" __type" ] = BT::demangle (typeid (T));
163+ }
164+ };
165+ to_json_converters_.insert ({ typeid (T), std::move (converter) });
166+ }
167+
168+ template <typename T>
169+ inline void
170+ JsonExporter::addConverter (std::function<void (const nlohmann::json&, T&)> func)
171+ {
172+ auto converter = [func](const nlohmann::json& json) -> Entry {
173+ T tmp;
174+ func (json, tmp);
175+ return { BT::Any (tmp), BT::TypeInfo::Create<T>() };
176+ };
177+ type_names_.insert ({ BT::demangle (typeid (T)), BT::TypeInfo::Create<T>() });
178+ from_json_converters_.insert ({ typeid (T), std::move (converter) });
179+ }
180+
120181template <typename T>
121182inline void RegisterJsonDefinition ()
122183{
0 commit comments