TreeTypedJSONConverter.cpp
Go to the documentation of this file.
2
3#include <SimoxUtility/json/eigen_conversion.h>
4
6
11
13{
15 {
16 jsonStack.push({"", nlohmann::json()});
17 }
18
19 const nlohmann::json&
21 {
22 nlohmann::json& obj = jsonStack.top().second;
23 if (obj.front().is_object())
24 {
25 return obj.front();
26 }
27 return obj;
28 }
29
30 /* We override this method because we need to handle untyped members in the hierarchy.
31 * The other get*Elements() methods will either not be called with a null type or can handle it.
32 */
35 {
36 return GetObjectElementsWithNullType(elementData, elementType);
37 }
38
39 void
41 {
42 std::string key = "";
43 aron::Path path;
44 if (elementData)
45 {
46 path = elementData->getPath();
47 }
48 else if (elementType)
49 {
50 path = elementType->getPath();
51 }
52 else
53 {
54 // should not happen
55 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
56 }
57
58 try
59 {
60 key = path.getLastElement();
61 if (!elementData)
62 {
63 // push NULL
64 jsonStack.push({key, nullptr});
65 }
66 else
67 {
68 // push new object as there is data
69 jsonStack.push({key, nlohmann::json(nlohmann::json::value_t::object)});
70 }
71 }
72 catch (const aron::error::AronException& e)
73 {
74 // This happens when we start at the top-level object.
75 jsonStack.push({key, nlohmann::json(nlohmann::json::value_t::object)});
76 }
77 }
78
79 void
81 TypeInput& /*elementType*/)
82 {
83 auto obj = jsonStack.top();
84 jsonStack.pop();
85 insertIntoJSON(obj.first, obj.second);
86 }
87
88 void
90 {
91 this->visitObjectOnEnter(elementData, elementType);
92 }
93
94 void
96 {
97 this->visitObjectOnExit(elementData, elementType);
98 }
99
100 void
102 {
103 this->visitListOnEnter(elementData, elementType);
104 }
105
106 void
108 {
109 this->visitListOnExit(elementData, elementType);
110 }
111
112 void
114 {
115 this->visitListOnEnter(elementData, elementType);
116 }
117
118 void
120 {
121 this->visitListOnExit(elementData, elementType);
122 }
123
124 void
126 {
127 std::string key = "";
128 aron::Path path;
129 if (elementData)
130 {
131 path = elementData->getPath();
132 }
133 else if (elementType)
134 {
135 path = elementType->getPath();
136 }
137 else
138 {
139 // should not happen
140 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
141 }
142
143 key = path.getLastElement();
144
145 if (!elementData)
146 {
147 jsonStack.push({key, nlohmann::json(nlohmann::json::value_t::array)});
148 }
149 else
150 {
151 jsonStack.push({key, nullptr});
152 }
153 }
154
155 void
157 {
158 auto list = jsonStack.top();
159 jsonStack.pop();
160 insertIntoJSON(list.first, list.second);
161 }
162
163 void
165 {
166 if (elementData)
167 {
168 auto e = aron::data::NDArray::DynamicCast(elementData);
169 auto t = *aron::type::Matrix::DynamicCastAndCheck(elementType);
170
171 auto& nd = *e;
172 const std::string key = nd.getPath().getLastElement();
173
174 nlohmann::json obj;
175 if (nd.getType() == "float") // TODO: are these types correct?
176 {
177 Eigen::Map<Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>> m(
178 reinterpret_cast<float*>(nd.getData()), t.getRows(), t.getCols());
179 Eigen::to_json(obj, m);
180 }
181 else if (nd.getType() == "double")
182 {
183 Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>> m(
184 reinterpret_cast<double*>(nd.getData()), t.getRows(), t.getCols());
185 Eigen::to_json(obj, m);
186 }
187 else
188 {
189 obj = handleGenericNDArray(nd);
190 }
191
192 insertIntoJSON(key, obj);
193 }
194 else if (elementType)
195 {
196 std::string key = elementType->getPath().getLastElement();
197 insertNULLIntoJSON(key);
198 }
199 else
200 {
201 // should not happen
202 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
203 }
204 }
205
206 void
208 {
209 if (elementData)
210 {
211 const std::string key = elementData->getPath().getLastElement();
212 auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData);
213 insertIntoJSON(key, handleGenericNDArray(nd));
214 }
215 else if (elementType)
216 {
217 std::string key = elementType->getPath().getLastElement();
218 insertNULLIntoJSON(key);
219 }
220 else
221 {
222 // should not happen
223 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
224 }
225 }
226
227 void
229 {
230 if (elementData)
231 {
232 const std::string key = elementData->getPath().getLastElement();
233 auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData);
234 nlohmann::json obj;
235 Eigen::to_json(obj,
237 insertIntoJSON(key, obj);
238 }
239 else if (elementType)
240 {
241 std::string key = elementType->getPath().getLastElement();
242 insertNULLIntoJSON(key);
243 }
244 else
245 {
246 // should not happen
247 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
248 }
249 }
250
251 void
253 {
254 if (elementData)
255 {
256 const std::string key = elementData->getPath().getLastElement();
257 auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData);
258 insertIntoJSON(key, handleGenericNDArray(nd));
259 }
260 else if (elementType)
261 {
262 std::string key = elementType->getPath().getLastElement();
263 insertNULLIntoJSON(key);
264 }
265 else
266 {
267 // should not happen
268 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
269 }
270 }
271
272 void
274 {
275 if (elementData)
276 {
277 const std::string key = elementData->getPath().getLastElement();
278 auto nd = *aron::data::NDArray::DynamicCastAndCheck(elementData);
279 insertIntoJSON(key, handleGenericNDArray(nd));
280 }
281 else if (elementType)
282 {
283 std::string key = elementType->getPath().getLastElement();
284 insertNULLIntoJSON(key);
285 }
286 else
287 {
288 // should not happen
289 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
290 }
291 }
292
293 void
295 {
296 this->visitInt(elementData, elementType);
297 }
298
299 void
301 {
302 if (elementData)
303 {
304 const std::string key = elementData->getPath().getLastElement();
305 int i = *aron::data::Int::DynamicCastAndCheck(elementData);
306 insertIntoJSON(key, i);
307 }
308 else if (elementType)
309 {
310 std::string key = elementType->getPath().getLastElement();
311 insertNULLIntoJSON(key);
312 }
313 else
314 {
315 // should not happen
316 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
317 }
318 }
319
320 void
322 {
323 if (elementData)
324 {
325 const std::string key = elementData->getPath().getLastElement();
326 int64_t l = *aron::data::Long::DynamicCastAndCheck(elementData);
327 insertIntoJSON(key, l);
328 }
329 else if (elementType)
330 {
331 std::string key = elementType->getPath().getLastElement();
332 insertNULLIntoJSON(key);
333 }
334 else
335 {
336 // should not happen
337 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
338 }
339 }
340
341 void
343 {
344 if (elementData)
345 {
346 const std::string key = elementData->getPath().getLastElement();
347 float f = *aron::data::Float::DynamicCastAndCheck(elementData);
348 insertIntoJSON(key, f);
349 }
350 else if (elementType)
351 {
352 std::string key = elementType->getPath().getLastElement();
353 insertNULLIntoJSON(key);
354 }
355 else
356 {
357 // should not happen
358 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
359 }
360 }
361
362 void
364 {
365 if (elementData)
366 {
367 const std::string key = elementData->getPath().getLastElement();
368 double d = *aron::data::Double::DynamicCastAndCheck(elementData);
369 insertIntoJSON(key, d);
370 }
371 else if (elementType)
372 {
373 std::string key = elementType->getPath().getLastElement();
374 insertNULLIntoJSON(key);
375 }
376 else
377 {
378 // should not happen
379 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
380 }
381 }
382
383 void
385 {
386 if (elementData)
387 {
388 const std::string key = elementData->getPath().getLastElement();
389 bool b = *aron::data::Bool::DynamicCastAndCheck(elementData);
390 insertIntoJSON(key, b);
391 }
392 else if (elementType)
393 {
394 std::string key = elementType->getPath().getLastElement();
395 insertNULLIntoJSON(key);
396 }
397 else
398 {
399 // should not happen
400 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
401 }
402 }
403
404 void
406 {
407 if (elementData)
408 {
409 const std::string key = elementData->getPath().getLastElement();
410 std::string s = *aron::data::String::DynamicCastAndCheck(elementData);
411 insertIntoJSON(key, s);
412 }
413 else if (elementType)
414 {
415 std::string key = elementType->getPath().getLastElement();
416 insertNULLIntoJSON(key);
417 }
418 else
419 {
420 // should not happen
421 throw aron::error::AronException(__PRETTY_FUNCTION__, "Both, data and type are NULL.");
422 }
423 }
424
425 //void
426 //TreeTypedJSONConverter::visitDateTime(DataInput& elementData, TypeInput& /*elementType*/)
427 /*{
428 const std::string key = elementData->getPath().getLastElement();
429 int64_t l = *aron::data::Long::DynamicCastAndCheck(elementData);
430 armem::Time time { armem::Duration::MicroSeconds(l) };
431 insertIntoJSON(key, l);
432 if (!jsonStack.top().second.is_array())
433 {
434 insertIntoJSON(key + "_hr", armem::toDateTimeMilliSeconds(time));
435 }
436 }*/
437
438 template <typename ElementType>
439 void
440 TreeTypedJSONConverter::insertIntoJSON(const std::string& key, const ElementType& data)
441 {
442 if (jsonStack.top().second.is_object())
443 {
444 jsonStack.top().second[key] = nlohmann::json(data);
445 }
446 else
447 {
448 jsonStack.top().second.emplace_back(data);
449 }
450 }
451
452 void
453 TreeTypedJSONConverter::insertNULLIntoJSON(const std::string& key)
454 {
455 if (jsonStack.top().second.is_object())
456 {
457 jsonStack.top().second[key] = nullptr;
458 }
459 else
460 {
461 jsonStack.top().second.emplace_back(nullptr);
462 }
463 }
464
465 nlohmann::json
466 TreeTypedJSONConverter::handleGenericNDArray(const aron::data::NDArray& nd)
467 {
468 nlohmann::json ndobj;
469 std::vector<int> shape = nd.getShape();
470 ndobj["dimensions"] = shape;
471 ndobj["type"] = nd.getType();
472
473 int elements =
474 shape.empty()
475 ? 0
476 : std::accumulate(std::begin(shape), std::end(shape), 1, std::multiplies<>());
477 std::vector<unsigned char> d = std::vector<unsigned char>(elements);
478 memcpy(d.data(), nd.getData(), elements);
479 ndobj["data"] = d;
480 return ndobj;
481 }
482} // namespace armarx::armem::gui::instance
void visitBool(DataInput &elementData, TypeInput &elementType) override
void visitNDArray(DataInput &elementData, TypeInput &elementType) override
void visitIntEnum(DataInput &elementData, TypeInput &elementType) override
void visitTupleOnEnter(DataInput &elementData, TypeInput &elementType) override
void visitPairOnExit(DataInput &elementData, TypeInput &elementType) override
void visitString(DataInput &elementData, TypeInput &elementType) override
void visitInt(DataInput &elementData, TypeInput &elementType) override
void visitDictOnExit(DataInput &elementData, TypeInput &elementType) override
void visitListOnEnter(DataInput &elementData, TypeInput &elementType) override
void visitObjectOnExit(DataInput &elementData, TypeInput &elementType) override
void visitPairOnEnter(DataInput &elementData, TypeInput &elementType) override
void visitQuaternion(DataInput &elementData, TypeInput &elementType) override
void visitImage(DataInput &elementData, TypeInput &elementType) override
void visitMatrix(DataInput &elementData, TypeInput &elementType) override
void visitTupleOnExit(DataInput &elementData, TypeInput &elementType) override
void visitDictOnEnter(DataInput &elementData, TypeInput &elementType) override
void visitObjectOnEnter(DataInput &elementData, TypeInput &elementType) override
void visitListOnExit(DataInput &elementData, TypeInput &elementType) override
MapElements getObjectElements(DataInput &elementData, TypeInput &elementType) override
void visitFloat(DataInput &elementData, TypeInput &elementType) override
void visitDouble(DataInput &elementData, TypeInput &elementType) override
void visitPointCloud(DataInput &elementData, TypeInput &elementType) override
void visitLong(DataInput &elementData, TypeInput &elementType) override
The Path class.
Definition Path.h:36
std::vector< std::string > getPath() const
Definition Path.cpp:87
std::string getLastElement() const
Definition Path.cpp:93
static Eigen::Quaternion< float > ConvertToQuaternionf(const data::NDArrayPtr &)
A base class for aron exceptions.
Definition Exception.h:37
ElementTypes::ElementType ElementType
static MapElements GetObjectElementsWithNullType(DataInput &o, TypeInput &t)
typename TypedVisitorBase< const data::VariantPtr, const type::VariantPtr >::TypeInput TypeInput
typename TypedVisitorBase< const data::VariantPtr, const type::VariantPtr >::DataInput DataInput
std::map< std::string, std::pair< DataInputNonConst, TypeInputNonConst > > MapElements