6
6
// Use the version nlohmann::json embedded in BT.CPP
7
7
#include " behaviortree_cpp/contrib/json.hpp"
8
8
9
- namespace BT
10
- {
9
+ namespace BT {
11
10
12
11
/* *
13
12
* To add new type, you must follow these isntructions:
14
13
* https://json.nlohmann.me/features/arbitrary_types/
15
14
*
16
- * For instance the type Foo requires the implementation:
15
+ * Considering for instance the type:
16
+ *
17
+ * struct Point2D {
18
+ * double x;
19
+ * double y;
20
+ * };
21
+ *
22
+ * This would require the implementation of:
23
+ *
24
+ * void to_json(nlohmann::json& j, const Point2D& point);
25
+ * void from_json(const nlohmann::json& j, Point2D& point);
17
26
*
18
- * void to_json(json& j, const Foo& f);
27
+ * To avoir repeating yourself, we provide the macro BT_JSON_CONVERTION
28
+ * that implements both those function, at once.
29
+ * Usage:
19
30
*
20
- * Later, you MUST register this calling:
31
+ * BT_JSON_CONVERTER(Point2D, point)
32
+ * {
33
+ * add_field("x", &point.x);
34
+ * add_field("y", &point.y);
35
+ * }
21
36
*
22
- * RegisterJsonDefinition<Foo>();
37
+ * Later, you MUST register the type in main using:
38
+ *
39
+ * RegisterJsonDefinition<Point2D>();
23
40
*/
24
41
25
- class JsonExporter {
42
+ // -----------------------------------------------------------------------------------
43
+
44
+ /* *
45
+ * Use RegisterJsonDefinition<Foo>();
46
+ */
47
+
48
+ class JsonExporter {
26
49
27
50
public:
28
51
static JsonExporter& get () {
@@ -43,81 +66,78 @@ class JsonExporter{
43
66
dst = val;
44
67
}
45
68
46
- // / Register new JSON converters with addConverter<Foo>(),
47
- // / But works only if this function is implemented:
48
- // /
49
- // / void nlohmann::to_json(nlohmann::json& destination, const Foo& foo)
50
- template <typename T> void addConverter ()
51
- {
52
- auto converter = [](const BT::Any& entry, nlohmann::json& dst) {
53
- nlohmann::to_json (dst, entry.cast <T>());
54
- };
55
- type_converters_.insert ( {typeid (T), std::move (converter)} );
56
- }
57
-
58
- template <typename T> void addConverter (std::function<void (nlohmann::json&, const T&)> func)
59
- {
60
- auto converter = [func](const BT::Any& entry, nlohmann::json& dst) {
61
- func (dst, entry.cast <T>());
62
- };
63
- type_converters_.insert ( {typeid (T), std::move (converter)} );
64
- }
65
-
66
- // / Register directly your own converter.
67
- template <typename T>
68
- void addConverter (std::function<void (const T&, nlohmann::json&)> to_json)
69
- {
70
- auto converter = [=](const BT::Any& entry, nlohmann::json& dst) {
71
- to_json (entry.cast <T>(), dst);
72
- };
73
- type_converters_.insert ( {typeid (T), std::move (converter)} );
74
- }
69
+ // / Register new JSON converters with addConverter<Foo>().
70
+ // / You should have used first the macro BT_JSON_CONVERTER
71
+ template <typename T> void addConverter ();
75
72
76
- private:
73
+ private:
77
74
78
75
using ToJonConverter = std::function<void (const BT::Any&, nlohmann::json&)>;
79
- std::unordered_map<std::type_index, ToJonConverter> type_converters_;
76
+ using FromJonConverter = std::function<BT::Any(const nlohmann::json&)>;
77
+
78
+ std::unordered_map<std::type_index, ToJonConverter> to_json_converters_;
79
+ std::unordered_map<std::string, FromJonConverter> from_json_converters_;
80
80
};
81
81
82
- /* Function to use to register a specific implementation of nlohmann::to_json
82
+ // -------------------------------------------------------------------
83
83
84
- Example:
84
+ template <typename T> inline
85
+ void JsonExporter::addConverter ()
86
+ {
87
+ ToJonConverter to_converter = [](const BT::Any& entry, nlohmann::json& dst)
88
+ {
89
+ using namespace nlohmann ;
90
+ to_json (dst, *const_cast <BT::Any&>(entry).castPtr <T>());
91
+ };
92
+ to_json_converters_.insert ( {typeid (T), to_converter} );
85
93
86
- namespace nlohmann {
87
- void to_json(nlohmann::json& j, const Position2D& p)
88
- {
89
- j["x"] = p.x;
90
- j["y"] = p.y;
91
- }
92
- } // namespace nlohmann
94
+ FromJonConverter from_converter = [](const nlohmann::json& dst) -> BT::Any
95
+ {
96
+ T value;
97
+ using namespace nlohmann ;
98
+ from_json (dst, value);
99
+ return BT::Any (value);
100
+ };
101
+
102
+ // we need to get the name of the type
103
+ nlohmann::json const js = T{};
104
+ auto const type_name = js.contains (" __type" ) ?
105
+ std::string (js[" __type" ]) :
106
+ BT::demangle (typeid (T));
107
+
108
+ from_json_converters_.insert ( {type_name, from_converter} );
109
+ }
93
110
94
- // In you main function
95
- RegisterJsonDefinition<Position2D>()
96
- */
97
111
template <typename T> inline void RegisterJsonDefinition ()
98
112
{
99
113
JsonExporter::get ().addConverter <T>();
100
114
}
101
115
102
- /* Function to use to register a specific implementation of "to_json"
103
-
104
- Example:
105
-
106
- RegisterJsonDefinition([](nlohmann::json& j, const Position2D& p)
107
- {
108
- j["x"] = p.x;
109
- j["y"] = p.y;
110
- } );
111
- */
112
-
113
- template <typename T> inline
114
- void RegisterJsonDefinition (std::function<void (nlohmann::json&, const T&)> func)
115
- {
116
- JsonExporter::get ().addConverter <T>(func);
117
- }
118
116
119
117
nlohmann::json ExportBlackboardToJSON (BT::Blackboard& blackboard);
120
118
121
119
} // namespace BT
122
120
121
+ // ------------------------------------------------
122
+ // ------------------------------------------------
123
+ // ------------------------------------------------
124
+
125
+ // Macro to implement to_json() and from_json()
126
+
127
+ #define BT_JSON_CONVERTER (Type, value ) \
128
+ template <class AddField > void _JsonTypeDefinition (Type&, AddField&); \
129
+ \
130
+ inline void to_json (nlohmann::json& js, const Type& p, bool add_type_name = false ) { \
131
+ auto op = [&js](const char * name, auto * val) { to_json (js[name], *val); }; \
132
+ _JsonTypeDefinition (const_cast <Type&>(p), op); \
133
+ js[" __type" ] = #Type; \
134
+ } \
135
+ \
136
+ inline void from_json (const nlohmann::json& js, Type& p) { \
137
+ auto op = [&js](const char * name, auto * v) { js.at (name).get_to (*v); }; \
138
+ _JsonTypeDefinition (p, op); \
139
+ } \
140
+ \
141
+ template <class AddField > inline \
142
+ void _JsonTypeDefinition (Type& value, AddField& add_field)\
123
143
0 commit comments