@@ -58,24 +58,74 @@ enum class PortDirection
5858
5959using StringView = std::string_view;
6060
61+ bool StartWith (StringView str, StringView prefix);
62+
6163// vector of key/value pairs
6264using KeyValueVector = std::vector<std::pair<std::string, std::string>>;
6365
66+ /* * Usage: given a function/method like this:
67+ *
68+ * Expected<double> getAnswer();
69+ *
70+ * User code can check result and error message like this:
71+ *
72+ * auto res = getAnswer();
73+ * if( res )
74+ * {
75+ * std::cout << "answer was: " << res.value() << std::endl;
76+ * }
77+ * else{
78+ * std::cerr << "failed to get the answer: " << res.error() << std::endl;
79+ * }
80+ *
81+ * */
82+ template <typename T>
83+ using Expected = nonstd::expected<T, std::string>;
84+
6485struct AnyTypeAllowed
6586{
6687};
6788
89+ /* *
90+ * @brief convertFromJSON will parse a json string and use JsonExporter
91+ * to convert its content to a given type. It will work only if
92+ * the type was previously registered. May throw if it fails.
93+ *
94+ * @param json_text a valid JSON string
95+ * @param type you must specify the typeid()
96+ * @return the object, wrapped in Any.
97+ */
98+ [[nodiscard]] Any convertFromJSON (StringView json_text, std::type_index type);
99+
100+ // / Same as the non template version, but with automatic casting
101+ template <typename T>
102+ [[nodiscard]] inline T convertFromJSON (StringView str)
103+ {
104+ return convertFromJSON (str, typeid (T)).cast <T>();
105+ }
106+
68107/* *
69108 * convertFromString is used to convert a string into a custom type.
70109 *
71110 * This function is invoked under the hood by TreeNode::getInput(), but only when the
72111 * input port contains a string.
73112 *
74- * If you have a custom type, you need to implement the corresponding template specialization.
113+ * If you have a custom type, you need to implement the corresponding
114+ * template specialization.
115+ *
116+ * If the string starts with the prefix "json:", it will
117+ * fall back to convertFromJSON()
75118 */
76119template <typename T>
77- [[nodiscard]] inline T convertFromString (StringView /* str*/ )
120+ [[nodiscard]] inline T convertFromString (StringView str)
78121{
122+ // if string starts with "json:{", try to parse it as json
123+ if (StartWith (str, " json:" ))
124+ {
125+ str.remove_prefix (5 );
126+ return convertFromJSON<T>(str);
127+ }
128+
79129 auto type_name = BT::demangle (typeid (T));
80130
81131 std::cerr << " You (maybe indirectly) called BT::convertFromString() for type ["
@@ -171,6 +221,14 @@ constexpr bool IsConvertibleToString()
171221 std::is_convertible_v<T, std::string_view>;
172222}
173223
224+ Expected<std::string> toJsonString (const Any& value);
225+
226+ /* *
227+ * @brief toStr is the reverse operation of convertFromString.
228+ *
229+ * If T is a custom type and there is no template specialization,
230+ * it will try to fall back to toJsonString()
231+ */
174232template <typename T>
175233[[nodiscard]] std::string toStr (const T& value)
176234{
@@ -180,6 +238,11 @@ template <typename T>
180238 }
181239 else if constexpr (!std::is_arithmetic_v<T>)
182240 {
241+ if (auto str = toJsonString (Any (value)))
242+ {
243+ return *str;
244+ }
245+
183246 throw LogicError (StrCat (" Function BT::toStr<T>() not specialized for type [" ,
184247 BT::demangle (typeid (T)), " ]" ));
185248 }
@@ -225,25 +288,6 @@ using enable_if = typename std::enable_if<Predicate::value>::type*;
225288template <typename Predicate>
226289using enable_if_not = typename std::enable_if<!Predicate::value>::type*;
227290
228- /* * Usage: given a function/method like this:
229- *
230- * Expected<double> getAnswer();
231- *
232- * User code can check result and error message like this:
233- *
234- * auto res = getAnswer();
235- * if( res )
236- * {
237- * std::cout << "answer was: " << res.value() << std::endl;
238- * }
239- * else{
240- * std::cerr << "failed to get the answer: " << res.error() << std::endl;
241- * }
242- *
243- * */
244- template <typename T>
245- using Expected = nonstd::expected<T, std::string>;
246-
247291#ifdef USE_BTCPP3_OLD_NAMES
248292// note: we also use the name Optional instead of expected because it is more intuitive
249293// for users that are not up to date with "modern" C++
0 commit comments