JSONObject.cpp
Go to the documentation of this file.
1/*
2* This file is part of ArmarX.
3*
4* Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5*
6* ArmarX is free software; you can redistribute it and/or modify
7* it under the terms of the GNU General Public License version 2 as
8* published by the Free Software Foundation.
9*
10* ArmarX is distributed in the hope that it will be useful, but
11* WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17*
18* @package ArmarX::Core
19* @author ALexey Kozlov ( kozlov at kit dot edu)
20* @date 2012
21* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22* GNU General Public License
23*/
24
25#include "JSONObject.h"
26
27#include <SimoxUtility/algorithm/string/string_tools.h>
28
31
32namespace armarx
33{
39
45
48 {
50 setIdField(toCopy.getIdField());
51 }
52
56
57 std::string
58 JSONObject::toString(const ::Ice::Current&) const
59 {
60 return asString(false);
61 }
62
63 std::string
64 JSONObject::asString(bool pretty /* = false */) const
65 {
66 if (pretty)
67 {
68 return jsonValue.toStyledString();
69 }
70 else
71 {
72 Json::FastWriter writer;
73 // writer.enableYAMLCompatibility();
74 std::string jsonString = writer.write(jsonValue);
75
76 // remove newline which is appended by jsoncpp
77 // MongoDB seems to have issues with it
78 while (jsonString.at(jsonString.size() - 1) == '\n')
79 {
80 jsonString.erase(jsonString.end() - 1);
81 }
82
83 return jsonString;
84 }
85 }
86
87 void
88 JSONObject::fromString(const ::std::string& jsonString, const ::Ice::Current&)
89 {
91 Json::Reader reader;
92 reader.parse(jsonString, jsonValue);
93 }
94
95 const Json::Value&
97 {
98 return jsonValue;
99 }
100
107
108 void
110 {
111 const JSONObjectPtr jsonObj = JSONObjectPtr::dynamicCast(obj);
112 jsonValue[key] = jsonObj->jsonValue;
113 }
114
115 void
116 JSONObject::setVariantArray(const std::string& key, const std::vector<VariantBasePtr>& val)
117 {
118 Json::Value arr(Json::arrayValue);
119
120 if (val.size() > 0)
121 {
122 arr.resize(val.size());
123
124 for (size_t i = 0; i < val.size(); ++i)
125 {
126 VariantPtr var = VariantPtr::dynamicCast(val.at(i));
128 const JSONObjectPtr jsonObj = JSONObjectPtr::dynamicCast(serial);
129 arr[int(i)] = jsonObj->jsonValue;
130 }
131 }
132
133 jsonValue[key] = arr;
134 }
135
136 void
137 JSONObject::setVariantArray(const std::string& key, const std::vector<VariantPtr>& val)
138 {
139 std::vector<VariantBasePtr> baseList;
140 baseList.resize(val.size());
141
142 for (unsigned int i = 0; i < val.size(); i++)
143 {
144 baseList.at(i) = val.at(i);
145 }
146
147 setVariantArray(key, baseList);
148 }
149
150 void
151 JSONObject::setVariantMap(const std::string& key, const StringVariantBaseMap& val)
152 {
153 Json::Value arr(Json::arrayValue);
154
155 if (val.size() > 0)
156 {
157 arr.resize(val.size());
158 size_t i = 0;
159
160 for (StringVariantBaseMap::const_iterator it = val.begin(); it != val.end(); ++it, i++)
161 {
162 VariantPtr var = VariantPtr::dynamicCast(it->second);
163 JSONObject json(ic);
164 json.setString("key", it->first);
165 json.setVariant("variant", var);
166 arr[int(i)] = json.jsonValue;
167 }
168 }
169
170 jsonValue[key] = arr;
171 }
172
173 void
175 {
176 const JSONObjectPtr jsonObj = JSONObjectPtr::dynamicCast(obj);
177 jsonValue[index] = jsonObj->jsonValue;
178 }
179
180 void
182 {
183 const JSONObjectPtr jsonObj = JSONObjectPtr::dynamicCast(obj);
184
185 if (jsonValue.isArray())
186 {
187 jsonValue.append(jsonObj->jsonValue);
188 }
189 else
190 {
191 throw JSONInvalidDataTypeException();
192 }
193 }
194
195 void
197 {
199 obj->getElementType() == armarx::ElementTypes::eObject)
200 {
201 const std::vector<std::string> elemNames = obj->getElementNames();
202
203 for (std::vector<std::string>::const_iterator it = elemNames.begin();
204 it != elemNames.end();
205 ++it)
206 {
207 set(*it, obj->getElement(*it));
208 }
209 }
210 else
211 {
212 throw JSONInvalidDataTypeException();
213 }
214 }
215
216 unsigned int
218 {
219 return jsonValue.size();
220 }
221
222 bool
223 JSONObject::hasElement(const ::std::string& key) const
224 {
225 return jsonValue.isMember(key);
226 }
227
228 void
229 JSONObject::get(const Json::Value& val, bool& result) const
230 {
231 if (!val.isBool())
232 {
233 throw JSONInvalidDataTypeException();
234 }
235 else
236 {
237 result = val.asBool();
238 }
239 }
240
241 void
242 JSONObject::get(const Json::Value& val, int& result) const
243 {
244 if (!val.isIntegral())
245 {
246 throw JSONInvalidDataTypeException();
247 }
248 else
249 {
250 result = val.asInt();
251 }
252 }
253
254 void
255 JSONObject::get(const Json::Value& val, float& result) const
256 {
257 if (!val.isNumeric())
258 {
259 throw JSONInvalidDataTypeException();
260 }
261 else
262 {
263 result = val.asFloat();
264 }
265 }
266
267 void
268 JSONObject::get(const Json::Value& val, double& result) const
269 {
270 if (!val.isNumeric())
271 {
272 throw JSONInvalidDataTypeException();
273 }
274 else
275 {
276 result = val.asDouble();
277 }
278 }
279
280 void
281 JSONObject::get(const Json::Value& val, std::string& result) const
282 {
283 if (!val.isString())
284 {
285 throw JSONInvalidDataTypeException();
286 }
287 else
288 {
289 result = val.asString();
290 }
291 }
292
293 const Json::Value&
294 JSONObject::getValue(const std::string& key) const
295 {
296 if (!jsonValue.isObject())
297 {
298 throw JSONInvalidDataTypeException("Attemping to get a key from a non object. key: " +
299 key);
300 }
301 if (key.find_first_of('.') > 0)
302 {
303 // the following code allows to get child fields using dot notation,
304 // e.g "position.mean.x"
305 std::vector<std::string> keys = simox::alg::split(key, ".");
306 Json::Value const* result = &jsonValue[keys[0]];
307
308 for (size_t i = 1; i < keys.size(); ++i)
309 if (result->isObject())
310 {
311 result = &((*result)[keys[i]]);
312 }
313 else
314 {
315 throw JSONInvalidFieldException(key);
316 }
317
318 return *result;
319 }
320 else
321 {
322 return jsonValue[key];
323 }
324 }
325
326 float
327 JSONObject::getFloat(const ::std::string& key) const
328 {
329 const Json::Value& val = getValue(key);
330
331 if (!val)
332 {
333 throw JSONInvalidFieldException(key);
334 }
335 else if (!val.isNumeric())
336 {
337 throw JSONInvalidDataTypeException();
338 }
339 else
340 {
341 return val.asFloat();
342 }
343 }
344
345 double
346 JSONObject::getDouble(const ::std::string& key) const
347 {
348 const Json::Value& val = getValue(key);
349
350 if (!val)
351 {
352 throw JSONInvalidFieldException(key);
353 }
354 else if (!val.isNumeric())
355 {
356 throw JSONInvalidDataTypeException();
357 }
358 else
359 {
360 return val.asDouble();
361 }
362 }
363
364 int
365 JSONObject::getInt(const ::std::string& key) const
366 {
367 const Json::Value& val = getValue(key);
368
369 if (!val)
370 {
371 throw JSONInvalidFieldException(key);
372 }
373 else if (!val.isInt())
374 {
375 throw JSONInvalidDataTypeException();
376 }
377 else
378 {
379 return val.asInt();
380 }
381 }
382
383 bool
384 JSONObject::getBool(const ::std::string& key) const
385 {
386 const Json::Value& val = getValue(key);
387
388 if (!val)
389 {
390 throw JSONInvalidFieldException(key);
391 }
392 else if (!val.isBool())
393 {
394 throw JSONInvalidDataTypeException();
395 }
396 else
397 {
398 return val.asBool();
399 }
400 }
401
402 std::string
403 JSONObject::getString(const ::std::string& key) const
404 {
405 const Json::Value& val = getValue(key);
406
407 if (!val)
408 {
409 ARMARX_IMPORTANT_S << "Invalid Field Exception for: " << key << " of object: \n"
410 << this->asString(true);
411 throw JSONInvalidFieldException(key);
412 }
413 else if (!val.isString())
414 {
415 throw JSONInvalidDataTypeException();
416 }
417 else
418 {
419 return val.asString();
420 }
421 }
422
424 JSONObject::getElement(unsigned int index) const
425 {
426 if (!jsonValue.isArray())
427 {
428 throw JSONInvalidDataTypeException();
429 }
430 else if (index >= jsonValue.size())
431 {
432 throw JSONInvalidArrayIndexException();
433 }
434 else
435 {
437 elem->jsonValue = jsonValue[index];
438 return elem;
439 }
440 }
441
443 JSONObject::getElement(const std::string& key) const
444 {
445 if (!jsonValue.isObject())
446 {
447 throw JSONInvalidDataTypeException();
448 }
449 else if (!jsonValue.isMember(key))
450 {
451 throw JSONInvalidFieldException(key);
452 }
453 else
454 {
456 elem->jsonValue = jsonValue[key];
457 return elem;
458 }
459 }
460
461 std::vector<std::string>
463 {
464 if (!jsonValue.isObject())
465 {
466 throw JSONInvalidDataTypeException();
467 }
468 else
469 {
470 return jsonValue.getMemberNames();
471 }
472 }
473
474 void
475 JSONObject::getVariantArray(const std::string& key, std::vector<VariantPtr>& result)
476 {
477 const Json::Value& arrValue = getValue(key);
478
479 if (!arrValue.isArray())
480 {
481 throw JSONInvalidDataTypeException();
482 }
483
484 result.clear();
485 result.resize(arrValue.size());
486
487 for (size_t i = 0; i < arrValue.size(); ++i)
488 {
489 JSONObjectPtr json = JSONObjectPtr::dynamicCast(createElement());
490 json->jsonValue = arrValue[int(i)];
491 VariantPtr var = json->deserializeVariant();
492 result.at(i) = var;
493 }
494 }
495
496 void
497 JSONObject::getVariantMap(const std::string& key, StringVariantBaseMap& result)
498 {
499 const Json::Value& arrValue = getValue(key);
500
501 if (!arrValue.isArray())
502 {
503 throw JSONInvalidDataTypeException();
504 }
505
506 result.clear();
507
508 for (size_t i = 0; i < arrValue.size(); ++i)
509 {
510 JSONObjectPtr json = JSONObjectPtr::dynamicCast(createElement());
511 json->jsonValue = arrValue[int(i)];
512 VariantPtr var = json->getVariant("variant");
513 result[json->getString("key")] = var;
514 }
515 }
516
518 JSONObject::getElementType(const ::Ice::Current&) const
519 {
520 if (jsonValue.isArray())
521 {
523 }
524 else if (jsonValue.isObject())
525 {
527 }
528 else
529 {
531 }
532 }
533
534 void
535 JSONObject::setElementType(armarx::ElementType elementType, const ::Ice::Current&)
536 {
537 switch (elementType)
538 {
540 jsonValue = Json::Value();
541 break;
542
544 jsonValue = Json::Value(Json::arrayValue);
545 break;
546
548 default:
549 jsonValue = Json::Value(Json::objectValue);
550 break;
551 }
552 }
553
554 void
556 {
557 jsonValue.clear();
558 }
559
562 const VariantBasePtr& variant)
563 {
564 JSONObjectPtr var;
565
566 if (variant)
567 {
568 var = JSONObjectPtr::dynamicCast(
569 serializer->serializeVariant(VariantPtr::dynamicCast(variant)));
570 }
571 else
572 {
573 var = serializer;
574 }
575
577
578 for (size_t i = 0; i < var->size(); i++)
579 {
580 // JSONObjectPtr elem = JSONObjectPtr::dynamicCast(var->getElement(i));
581 auto names = var->getElementNames();
582
583 for (auto name : names)
584 {
585 JSONObjectPtr elem = JSONObjectPtr::dynamicCast(var->getElement(name));
586
587 if (elem->getElementType() == armarx::ElementTypes::eScalar)
588 {
589 if (elem->jsonValue.isBool())
590 {
591 result[name] = new Variant(var->getBool(name));
592 }
593 else if (elem->jsonValue.isString())
594 {
595 result[name] = new Variant(var->getString(name));
596 }
597 else if (elem->jsonValue.isDouble())
598 {
599 result[name] = new Variant(var->getDouble(name));
600 }
601 else if (elem->jsonValue.isInt())
602 {
603 result[name] = new Variant(var->getInt(name));
604 }
605 else
606 {
607 throw LocalException() << "Unhandled type in variant to Dict conversion: "
608 << elem->jsonValue.type();
609 }
610 }
611 else
612 {
613 auto subResult = ConvertToBasicVariantMap(elem, nullptr);
614
615 for (auto& entry : subResult)
616 {
617 result[name + "." + entry.first] = entry.second;
618 }
619 }
620 }
621 }
622
623 return result;
624 }
625} // namespace armarx
uint8_t index
void setIdField(const std::string &fieldName)
AbstractObjectSerializerPtr serializeVariant(const VariantPtr &val) const
virtual void setVariant(const ::std::string &key, const VariantPtr &val)
std::vector< std::string > getElementNames() const override
void setVariantArray(const ::std::string &key, const std::vector< armarx::VariantBasePtr > &val) override
unsigned int size() const override
std::string toString(const ::Ice::Current &=Ice::emptyCurrent) const override
double getDouble(const ::std::string &key) const override
std::string asString(bool pretty=false) const
const Json::Value & getJsonValue() const
float getFloat(const ::std::string &key) const override
armarx::ElementType getElementType(const ::Ice::Current &=Ice::emptyCurrent) const override
std::string getString(const ::std::string &key) const override
void setString(const ::std::string &key, const std::string &val) override
Definition JSONObject.h:182
void setElement(const ::std::string &key, const armarx::AbstractObjectSerializerPtr &obj) override
int getInt(const ::std::string &key) const override
JSONObject(armarx::ElementType nodeType=armarx::ElementTypes::eObject, const Ice::CommunicatorPtr ic=Ice::CommunicatorPtr())
bool hasElement(const ::std::string &key) const override
armarx::AbstractObjectSerializerPtr createElement() const override
void fromString(const ::std::string &jsonString, const ::Ice::Current &=Ice::emptyCurrent) override
static StringVariantBaseMap ConvertToBasicVariantMap(const JSONObjectPtr &serializer, const VariantBasePtr &variant)
bool getBool(const ::std::string &key) const override
void getVariantArray(const ::std::string &key, std::vector< armarx::VariantPtr > &result) override
void set(const ::std::string &key, T val)
Definition JSONObject.h:126
void merge(const armarx::AbstractObjectSerializerPtr &val) override
armarx::AbstractObjectSerializerPtr getElement(unsigned int index) const override
~JSONObject() override
void getVariantMap(const ::std::string &key, armarx::StringVariantBaseMap &result) override
void setVariantMap(const ::std::string &key, const armarx::StringVariantBaseMap &val) override
void reset() override
void append(const armarx::AbstractObjectSerializerPtr &val) override
void setElementType(armarx::ElementType nodeType, const ::Ice::Current &=Ice::emptyCurrent) override
The Variant class is described here: Variants.
Definition Variant.h:224
#define ARMARX_IMPORTANT_S
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:210
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
Definition IceManager.h:49
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::map< std::string, VariantBasePtr > StringVariantBaseMap
IceInternal::Handle< Variant > VariantPtr
Definition Variant.h:41
IceInternal::Handle< AbstractObjectSerializer > AbstractObjectSerializerPtr
ElementTypes::ElementType ElementType
IceInternal::Handle< JSONObject > JSONObjectPtr
Definition JSONObject.h:34
::IceInternal::Handle<::armarx::VariantBase > VariantBasePtr