JsonObject.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/crt/JsonObject.h>
  6. #include <aws/crt/external/cJSON.h>
  7. #include <algorithm>
  8. #include <iterator>
  9. namespace Aws
  10. {
  11. namespace Crt
  12. {
  13. JsonObject::JsonObject() : m_wasParseSuccessful(true) { m_value = nullptr; }
  14. JsonObject::JsonObject(cJSON *value)
  15. : m_value(cJSON_Duplicate(value, 1 /* recurse */)), m_wasParseSuccessful(true)
  16. {
  17. }
  18. JsonObject::JsonObject(const String &value) : m_wasParseSuccessful(true)
  19. {
  20. const char *return_parse_end;
  21. m_value = cJSON_ParseWithLengthOpts(value.c_str(), value.length(), &return_parse_end, 0);
  22. if (m_value == nullptr || cJSON_IsInvalid(m_value) == 1)
  23. {
  24. m_wasParseSuccessful = false;
  25. m_errorMessage = "Failed to parse JSON at: ";
  26. m_errorMessage += return_parse_end;
  27. }
  28. }
  29. JsonObject::JsonObject(const JsonObject &value)
  30. : m_value(cJSON_Duplicate(value.m_value, 1 /*recurse*/)), m_wasParseSuccessful(value.m_wasParseSuccessful),
  31. m_errorMessage(value.m_errorMessage)
  32. {
  33. }
  34. JsonObject::JsonObject(JsonObject &&value) noexcept
  35. : m_value(value.m_value), m_wasParseSuccessful(value.m_wasParseSuccessful),
  36. m_errorMessage(std::move(value.m_errorMessage))
  37. {
  38. value.m_value = nullptr;
  39. }
  40. void JsonObject::Destroy() { cJSON_Delete(m_value); }
  41. JsonObject::~JsonObject() { Destroy(); }
  42. JsonObject &JsonObject::operator=(const JsonObject &other)
  43. {
  44. if (this == &other)
  45. {
  46. return *this;
  47. }
  48. Destroy();
  49. m_value = cJSON_Duplicate(other.m_value, 1 /*recurse*/);
  50. m_wasParseSuccessful = other.m_wasParseSuccessful;
  51. m_errorMessage = other.m_errorMessage;
  52. return *this;
  53. }
  54. JsonObject &JsonObject::operator=(JsonObject &&other) noexcept
  55. {
  56. if (this == &other)
  57. {
  58. return *this;
  59. }
  60. using std::swap;
  61. swap(m_value, other.m_value);
  62. swap(m_errorMessage, other.m_errorMessage);
  63. m_wasParseSuccessful = other.m_wasParseSuccessful;
  64. return *this;
  65. }
  66. static void AddOrReplace(cJSON *root, const char *key, cJSON *value)
  67. {
  68. const auto existing = cJSON_GetObjectItemCaseSensitive(root, key);
  69. if (existing != nullptr)
  70. {
  71. cJSON_ReplaceItemInObjectCaseSensitive(root, key, value);
  72. }
  73. else
  74. {
  75. cJSON_AddItemToObject(root, key, value);
  76. }
  77. }
  78. JsonObject &JsonObject::WithString(const char *key, const String &value)
  79. {
  80. if (m_value == nullptr)
  81. {
  82. m_value = cJSON_CreateObject();
  83. }
  84. const auto val = cJSON_CreateString(value.c_str());
  85. AddOrReplace(m_value, key, val);
  86. return *this;
  87. }
  88. JsonObject &JsonObject::WithString(const String &key, const String &value)
  89. {
  90. return WithString(key.c_str(), value);
  91. }
  92. JsonObject &JsonObject::AsString(const String &value)
  93. {
  94. Destroy();
  95. m_value = cJSON_CreateString(value.c_str());
  96. return *this;
  97. }
  98. JsonObject &JsonObject::WithBool(const char *key, bool value)
  99. {
  100. if (m_value == nullptr)
  101. {
  102. m_value = cJSON_CreateObject();
  103. }
  104. const auto val = cJSON_CreateBool((cJSON_bool)value);
  105. AddOrReplace(m_value, key, val);
  106. return *this;
  107. }
  108. JsonObject &JsonObject::WithBool(const String &key, bool value) { return WithBool(key.c_str(), value); }
  109. JsonObject &JsonObject::AsBool(bool value)
  110. {
  111. Destroy();
  112. m_value = cJSON_CreateBool((cJSON_bool)value);
  113. return *this;
  114. }
  115. JsonObject &JsonObject::WithInteger(const char *key, int value)
  116. {
  117. return WithDouble(key, static_cast<double>(value));
  118. }
  119. JsonObject &JsonObject::WithInteger(const String &key, int value)
  120. {
  121. return WithDouble(key.c_str(), static_cast<double>(value));
  122. }
  123. JsonObject &JsonObject::AsInteger(int value)
  124. {
  125. Destroy();
  126. m_value = cJSON_CreateNumber(static_cast<double>(value));
  127. return *this;
  128. }
  129. JsonObject &JsonObject::WithInt64(const char *key, int64_t value)
  130. {
  131. return WithDouble(key, static_cast<double>(value));
  132. }
  133. JsonObject &JsonObject::WithInt64(const String &key, int64_t value)
  134. {
  135. return WithDouble(key.c_str(), static_cast<double>(value));
  136. }
  137. JsonObject &JsonObject::AsInt64(int64_t value) { return AsDouble(static_cast<double>(value)); }
  138. JsonObject &JsonObject::WithDouble(const char *key, double value)
  139. {
  140. if (m_value == nullptr)
  141. {
  142. m_value = cJSON_CreateObject();
  143. }
  144. const auto val = cJSON_CreateNumber(value);
  145. AddOrReplace(m_value, key, val);
  146. return *this;
  147. }
  148. JsonObject &JsonObject::WithDouble(const String &key, double value) { return WithDouble(key.c_str(), value); }
  149. JsonObject &JsonObject::AsDouble(double value)
  150. {
  151. Destroy();
  152. m_value = cJSON_CreateNumber(value);
  153. return *this;
  154. }
  155. JsonObject &JsonObject::WithArray(const char *key, const Vector<String> &array)
  156. {
  157. if (m_value == nullptr)
  158. {
  159. m_value = cJSON_CreateObject();
  160. }
  161. auto arrayValue = cJSON_CreateArray();
  162. for (const auto &i : array)
  163. {
  164. cJSON_AddItemToArray(arrayValue, cJSON_CreateString(i.c_str()));
  165. }
  166. AddOrReplace(m_value, key, arrayValue);
  167. return *this;
  168. }
  169. JsonObject &JsonObject::WithArray(const String &key, const Vector<String> &array)
  170. {
  171. return WithArray(key.c_str(), array);
  172. }
  173. JsonObject &JsonObject::WithArray(const String &key, const Vector<JsonObject> &array)
  174. {
  175. if (m_value == nullptr)
  176. {
  177. m_value = cJSON_CreateObject();
  178. }
  179. auto arrayValue = cJSON_CreateArray();
  180. for (const auto &i : array)
  181. {
  182. cJSON_AddItemToArray(arrayValue, cJSON_Duplicate(i.m_value, 1 /*recurse*/));
  183. }
  184. AddOrReplace(m_value, key.c_str(), arrayValue);
  185. return *this;
  186. }
  187. JsonObject &JsonObject::WithArray(const String &key, Vector<JsonObject> &&array)
  188. {
  189. if (m_value == nullptr)
  190. {
  191. m_value = cJSON_CreateObject();
  192. }
  193. auto arrayValue = cJSON_CreateArray();
  194. for (auto &i : array)
  195. {
  196. cJSON_AddItemToArray(arrayValue, i.m_value);
  197. i.m_value = nullptr;
  198. }
  199. AddOrReplace(m_value, key.c_str(), arrayValue);
  200. return *this;
  201. }
  202. JsonObject &JsonObject::AsArray(const Vector<JsonObject> &array)
  203. {
  204. auto arrayValue = cJSON_CreateArray();
  205. for (const auto &i : array)
  206. {
  207. cJSON_AddItemToArray(arrayValue, cJSON_Duplicate(i.m_value, 1 /*recurse*/));
  208. }
  209. Destroy();
  210. m_value = arrayValue;
  211. return *this;
  212. }
  213. JsonObject &JsonObject::AsArray(Vector<JsonObject> &&array)
  214. {
  215. auto arrayValue = cJSON_CreateArray();
  216. for (auto &i : array)
  217. {
  218. cJSON_AddItemToArray(arrayValue, i.m_value);
  219. i.m_value = nullptr;
  220. }
  221. Destroy();
  222. m_value = arrayValue;
  223. return *this;
  224. }
  225. JsonObject &JsonObject::AsNull()
  226. {
  227. m_value = cJSON_CreateNull();
  228. return *this;
  229. }
  230. JsonObject &JsonObject::WithObject(const char *key, const JsonObject &value)
  231. {
  232. if (m_value == nullptr)
  233. {
  234. m_value = cJSON_CreateObject();
  235. }
  236. const auto copy =
  237. value.m_value == nullptr ? cJSON_CreateObject() : cJSON_Duplicate(value.m_value, 1 /*recurse*/);
  238. AddOrReplace(m_value, key, copy);
  239. return *this;
  240. }
  241. JsonObject &JsonObject::WithObject(const String &key, const JsonObject &value)
  242. {
  243. return WithObject(key.c_str(), value);
  244. }
  245. JsonObject &JsonObject::WithObject(const char *key, JsonObject &&value)
  246. {
  247. if (m_value == nullptr)
  248. {
  249. m_value = cJSON_CreateObject();
  250. }
  251. AddOrReplace(m_value, key, value.m_value == nullptr ? cJSON_CreateObject() : value.m_value);
  252. value.m_value = nullptr;
  253. return *this;
  254. }
  255. JsonObject &JsonObject::WithObject(const String &key, JsonObject &&value)
  256. {
  257. return WithObject(key.c_str(), std::move(value));
  258. }
  259. JsonObject &JsonObject::AsObject(const JsonObject &value)
  260. {
  261. *this = value;
  262. return *this;
  263. }
  264. JsonObject &JsonObject::AsObject(JsonObject &&value)
  265. {
  266. *this = std::move(value);
  267. return *this;
  268. }
  269. bool JsonObject::operator==(const JsonObject &other) const
  270. {
  271. return cJSON_Compare(m_value, other.m_value, 1 /*case-sensitive*/) != 0;
  272. }
  273. bool JsonObject::operator!=(const JsonObject &other) const { return !(*this == other); }
  274. JsonView JsonObject::View() const { return *this; }
  275. JsonView::JsonView() : m_value(nullptr) {}
  276. JsonView::JsonView(const JsonObject &val) : m_value(val.m_value) {}
  277. JsonView::JsonView(cJSON *val) : m_value(val) {}
  278. JsonView &JsonView::operator=(const JsonObject &v)
  279. {
  280. m_value = v.m_value;
  281. return *this;
  282. }
  283. JsonView &JsonView::operator=(cJSON *val)
  284. {
  285. m_value = val;
  286. return *this;
  287. }
  288. String JsonView::GetString(const String &key) const { return GetString(key.c_str()); }
  289. String JsonView::GetString(const char *key) const
  290. {
  291. AWS_ASSERT(m_value);
  292. auto item = cJSON_GetObjectItemCaseSensitive(m_value, key);
  293. auto str = cJSON_GetStringValue(item);
  294. return str != nullptr ? str : "";
  295. }
  296. String JsonView::AsString() const
  297. {
  298. const char *str = cJSON_GetStringValue(m_value);
  299. if (str == nullptr)
  300. {
  301. return {};
  302. }
  303. return str;
  304. }
  305. bool JsonView::GetBool(const String &key) const { return GetBool(key.c_str()); }
  306. bool JsonView::GetBool(const char *key) const
  307. {
  308. AWS_ASSERT(m_value);
  309. auto item = cJSON_GetObjectItemCaseSensitive(m_value, key);
  310. AWS_ASSERT(item);
  311. return cJSON_IsTrue(item) != 0;
  312. }
  313. bool JsonView::AsBool() const
  314. {
  315. AWS_ASSERT(cJSON_IsBool(m_value));
  316. return cJSON_IsTrue(m_value) != 0;
  317. }
  318. int JsonView::GetInteger(const String &key) const { return GetInteger(key.c_str()); }
  319. int JsonView::GetInteger(const char *key) const
  320. {
  321. AWS_ASSERT(m_value);
  322. auto item = cJSON_GetObjectItemCaseSensitive(m_value, key);
  323. AWS_ASSERT(item);
  324. return item->valueint;
  325. }
  326. int JsonView::AsInteger() const
  327. {
  328. AWS_ASSERT(cJSON_IsNumber(m_value)); // can be double or value larger than int_max, but at least not UB
  329. return m_value->valueint;
  330. }
  331. int64_t JsonView::GetInt64(const String &key) const { return static_cast<int64_t>(GetDouble(key)); }
  332. int64_t JsonView::GetInt64(const char *key) const { return static_cast<int64_t>(GetDouble(key)); }
  333. int64_t JsonView::AsInt64() const
  334. {
  335. AWS_ASSERT(cJSON_IsNumber(m_value));
  336. return static_cast<int64_t>(m_value->valuedouble);
  337. }
  338. double JsonView::GetDouble(const String &key) const { return GetDouble(key.c_str()); }
  339. double JsonView::GetDouble(const char *key) const
  340. {
  341. AWS_ASSERT(m_value);
  342. auto item = cJSON_GetObjectItemCaseSensitive(m_value, key);
  343. AWS_ASSERT(item);
  344. return item->valuedouble;
  345. }
  346. double JsonView::AsDouble() const
  347. {
  348. AWS_ASSERT(cJSON_IsNumber(m_value));
  349. return m_value->valuedouble;
  350. }
  351. JsonView JsonView::GetJsonObject(const String &key) const { return GetJsonObject(key.c_str()); }
  352. JsonView JsonView::GetJsonObject(const char *key) const
  353. {
  354. AWS_ASSERT(m_value);
  355. auto item = cJSON_GetObjectItemCaseSensitive(m_value, key);
  356. return item;
  357. }
  358. JsonObject JsonView::GetJsonObjectCopy(const String &key) const { return GetJsonObjectCopy(key.c_str()); }
  359. JsonObject JsonView::GetJsonObjectCopy(const char *key) const
  360. {
  361. AWS_ASSERT(m_value);
  362. /* force a deep copy */
  363. return JsonObject(cJSON_GetObjectItemCaseSensitive(m_value, key));
  364. }
  365. JsonView JsonView::AsObject() const
  366. {
  367. AWS_ASSERT(cJSON_IsObject(m_value));
  368. return m_value;
  369. }
  370. Vector<JsonView> JsonView::GetArray(const String &key) const { return GetArray(key.c_str()); }
  371. Vector<JsonView> JsonView::GetArray(const char *key) const
  372. {
  373. AWS_ASSERT(m_value);
  374. auto array = cJSON_GetObjectItemCaseSensitive(m_value, key);
  375. AWS_ASSERT(cJSON_IsArray(array));
  376. Vector<JsonView> returnArray(static_cast<size_t>(cJSON_GetArraySize(array)));
  377. auto element = array->child;
  378. for (size_t i = 0; element != nullptr && i < returnArray.size(); ++i, element = element->next)
  379. {
  380. returnArray[i] = element;
  381. }
  382. return returnArray;
  383. }
  384. Vector<JsonView> JsonView::AsArray() const
  385. {
  386. AWS_ASSERT(cJSON_IsArray(m_value));
  387. Vector<JsonView> returnArray(static_cast<size_t>(cJSON_GetArraySize(m_value)));
  388. auto element = m_value->child;
  389. for (size_t i = 0; element != nullptr && i < returnArray.size(); ++i, element = element->next)
  390. {
  391. returnArray[i] = element;
  392. }
  393. return returnArray;
  394. }
  395. Map<String, JsonView> JsonView::GetAllObjects() const
  396. {
  397. Map<String, JsonView> valueMap;
  398. if (m_value == nullptr)
  399. {
  400. return valueMap;
  401. }
  402. for (auto iter = m_value->child; iter != nullptr; iter = iter->next)
  403. {
  404. valueMap.emplace(std::make_pair(String(iter->string), JsonView(iter)));
  405. }
  406. return valueMap;
  407. }
  408. bool JsonView::ValueExists(const String &key) const { return ValueExists(key.c_str()); }
  409. bool JsonView::ValueExists(const char *key) const
  410. {
  411. if (cJSON_IsObject(m_value) == 0)
  412. {
  413. return false;
  414. }
  415. auto item = cJSON_GetObjectItemCaseSensitive(m_value, key);
  416. return !(item == nullptr || cJSON_IsNull(item) != 0);
  417. }
  418. bool JsonView::KeyExists(const String &key) const { return KeyExists(key.c_str()); }
  419. bool JsonView::KeyExists(const char *key) const
  420. {
  421. if (cJSON_IsObject(m_value) == 0)
  422. {
  423. return false;
  424. }
  425. return cJSON_GetObjectItemCaseSensitive(m_value, key) != nullptr;
  426. }
  427. bool JsonView::IsObject() const { return cJSON_IsObject(m_value) != 0; }
  428. bool JsonView::IsBool() const { return cJSON_IsBool(m_value) != 0; }
  429. bool JsonView::IsString() const { return cJSON_IsString(m_value) != 0; }
  430. bool JsonView::IsIntegerType() const
  431. {
  432. if (cJSON_IsNumber(m_value) == 0)
  433. {
  434. return false;
  435. }
  436. return m_value->valuedouble == static_cast<int64_t>(m_value->valuedouble);
  437. }
  438. bool JsonView::IsFloatingPointType() const
  439. {
  440. if (cJSON_IsNumber(m_value) == 0)
  441. {
  442. return false;
  443. }
  444. return m_value->valuedouble != static_cast<int64_t>(m_value->valuedouble);
  445. }
  446. bool JsonView::IsListType() const { return cJSON_IsArray(m_value) != 0; }
  447. bool JsonView::IsNull() const { return cJSON_IsNull(m_value) != 0; }
  448. String JsonView::WriteCompact(bool treatAsObject) const
  449. {
  450. if (m_value == nullptr)
  451. {
  452. if (treatAsObject)
  453. {
  454. return "{}";
  455. }
  456. return "";
  457. }
  458. auto temp = cJSON_PrintUnformatted(m_value);
  459. String out(temp);
  460. cJSON_free(temp);
  461. return out;
  462. }
  463. String JsonView::WriteReadable(bool treatAsObject) const
  464. {
  465. if (m_value == nullptr)
  466. {
  467. if (treatAsObject)
  468. {
  469. return "{\n}\n";
  470. }
  471. return "";
  472. }
  473. auto temp = cJSON_Print(m_value);
  474. String out(temp);
  475. cJSON_free(temp);
  476. return out;
  477. }
  478. JsonObject JsonView::Materialize() const { return m_value; }
  479. } // namespace Crt
  480. } // namespace Aws