Document.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/core/utils/Document.h>
  6. #include <iterator>
  7. #include <algorithm>
  8. #include <aws/core/utils/memory/stl/AWSStringStream.h>
  9. #include <aws/core/utils/StringUtils.h>
  10. #include <aws/core/utils/json/JsonSerializer.h>
  11. using namespace Aws::Utils;
  12. Document::Document() : m_wasParseSuccessful(true)
  13. {
  14. m_json = nullptr;
  15. }
  16. Document::Document(cJSON* value) :
  17. m_json(cJSON_AS4CPP_Duplicate(value, true /* recurse */)),
  18. m_wasParseSuccessful(true)
  19. {
  20. }
  21. Document::Document(const Aws::String& value) : m_wasParseSuccessful(true)
  22. {
  23. const char* return_parse_end;
  24. m_json = cJSON_AS4CPP_ParseWithOpts(value.c_str(), &return_parse_end, 1/*require_null_terminated*/);
  25. if (!m_json || cJSON_AS4CPP_IsInvalid(m_json))
  26. {
  27. m_wasParseSuccessful = false;
  28. m_errorMessage = "Failed to parse JSON at: ";
  29. m_errorMessage += return_parse_end;
  30. }
  31. }
  32. Document::Document(Aws::IStream& istream) : m_wasParseSuccessful(true)
  33. {
  34. Aws::StringStream memoryStream;
  35. std::copy(std::istreambuf_iterator<char>(istream), std::istreambuf_iterator<char>(), std::ostreambuf_iterator<char>(memoryStream));
  36. const char* return_parse_end;
  37. const auto input = memoryStream.str();
  38. m_json = cJSON_AS4CPP_ParseWithOpts(input.c_str(), &return_parse_end, 1/*require_null_terminated*/);
  39. if (!m_json || cJSON_AS4CPP_IsInvalid(m_json))
  40. {
  41. m_wasParseSuccessful = false;
  42. m_errorMessage = "Failed to parse JSON. Invalid input at: ";
  43. m_errorMessage += return_parse_end;
  44. }
  45. }
  46. Document::Document(const Document& value) :
  47. m_json(cJSON_AS4CPP_Duplicate(value.m_json, true/*recurse*/)),
  48. m_wasParseSuccessful(value.m_wasParseSuccessful),
  49. m_errorMessage(value.m_errorMessage)
  50. {
  51. }
  52. Document::Document(Document&& value) :
  53. m_json(value.m_json),
  54. m_wasParseSuccessful(value.m_wasParseSuccessful),
  55. m_errorMessage(std::move(value.m_errorMessage))
  56. {
  57. value.m_json = nullptr;
  58. }
  59. Document::Document(const Json::JsonView& view) :
  60. m_json(cJSON_AS4CPP_Duplicate(view.m_value, true/*recurse*/)),
  61. m_wasParseSuccessful(true),
  62. m_errorMessage({})
  63. {
  64. }
  65. void Document::Destroy()
  66. {
  67. cJSON_AS4CPP_Delete(m_json);
  68. }
  69. Document::~Document()
  70. {
  71. Destroy();
  72. }
  73. Document& Document::operator=(const Document& other)
  74. {
  75. if (this == &other)
  76. {
  77. return *this;
  78. }
  79. Destroy();
  80. m_json = cJSON_AS4CPP_Duplicate(other.m_json, true /*recurse*/);
  81. m_wasParseSuccessful = other.m_wasParseSuccessful;
  82. m_errorMessage = other.m_errorMessage;
  83. return *this;
  84. }
  85. Document& Document::operator=(Document&& other)
  86. {
  87. if (this == &other)
  88. {
  89. return *this;
  90. }
  91. using std::swap;
  92. swap(m_json, other.m_json);
  93. swap(m_errorMessage, other.m_errorMessage);
  94. m_wasParseSuccessful = other.m_wasParseSuccessful;
  95. return *this;
  96. }
  97. Document& Document::operator=(const Json::JsonView& other)
  98. {
  99. Destroy();
  100. m_json = cJSON_AS4CPP_Duplicate(other.m_value, true /*recurse*/);
  101. m_wasParseSuccessful = true;
  102. m_errorMessage = {};
  103. return *this;
  104. }
  105. bool Document::operator==(const Document& other) const
  106. {
  107. return cJSON_AS4CPP_Compare(m_json, other.m_json, true /*case-sensitive*/) != 0;
  108. }
  109. bool Document::operator!=(const Document& other) const
  110. {
  111. return !(*this == other);
  112. }
  113. static void AddOrReplace(cJSON* root, const char* key, cJSON* value)
  114. {
  115. const auto existing = cJSON_AS4CPP_GetObjectItemCaseSensitive(root, key);
  116. if (existing)
  117. {
  118. cJSON_AS4CPP_ReplaceItemInObjectCaseSensitive(root, key, value);
  119. }
  120. else
  121. {
  122. cJSON_AS4CPP_AddItemToObject(root, key, value);
  123. }
  124. }
  125. Document& Document::WithString(const char* key, const Aws::String& value)
  126. {
  127. if (!m_json)
  128. {
  129. m_json = cJSON_AS4CPP_CreateObject();
  130. }
  131. const auto val = cJSON_AS4CPP_CreateString(value.c_str());
  132. AddOrReplace(m_json, key, val);
  133. return *this;
  134. }
  135. Document& Document::WithString(const Aws::String& key, const Aws::String& value)
  136. {
  137. return WithString(key.c_str(), value);
  138. }
  139. Document& Document::AsString(const Aws::String& value)
  140. {
  141. Destroy();
  142. m_json = cJSON_AS4CPP_CreateString(value.c_str());
  143. return *this;
  144. }
  145. Document& Document::WithBool(const char* key, bool value)
  146. {
  147. if (!m_json)
  148. {
  149. m_json = cJSON_AS4CPP_CreateObject();
  150. }
  151. const auto val = cJSON_AS4CPP_CreateBool(value);
  152. AddOrReplace(m_json, key, val);
  153. return *this;
  154. }
  155. Document& Document::WithBool(const Aws::String& key, bool value)
  156. {
  157. return WithBool(key.c_str(), value);
  158. }
  159. Document& Document::AsBool(bool value)
  160. {
  161. Destroy();
  162. m_json = cJSON_AS4CPP_CreateBool(value);
  163. return *this;
  164. }
  165. Document& Document::WithInteger(const char* key, int value)
  166. {
  167. return WithDouble(key, static_cast<double>(value));
  168. }
  169. Document& Document::WithInteger(const Aws::String& key, int value)
  170. {
  171. return WithDouble(key.c_str(), static_cast<double>(value));
  172. }
  173. Document& Document::AsInteger(int value)
  174. {
  175. Destroy();
  176. m_json = cJSON_AS4CPP_CreateNumber(static_cast<double>(value));
  177. return *this;
  178. }
  179. Document& Document::WithInt64(const char* key, long long value)
  180. {
  181. if (!m_json)
  182. {
  183. m_json = cJSON_AS4CPP_CreateObject();
  184. }
  185. const auto val = cJSON_AS4CPP_CreateInt64(value);
  186. AddOrReplace(m_json, key, val);
  187. return *this;
  188. }
  189. Document& Document::WithInt64(const Aws::String& key, long long value)
  190. {
  191. return WithInt64(key.c_str(), value);
  192. }
  193. Document& Document::AsInt64(long long value)
  194. {
  195. Destroy();
  196. m_json = cJSON_AS4CPP_CreateInt64(value);
  197. return *this;
  198. }
  199. Document& Document::WithDouble(const char* key, double value)
  200. {
  201. if (!m_json)
  202. {
  203. m_json = cJSON_AS4CPP_CreateObject();
  204. }
  205. const auto val = cJSON_AS4CPP_CreateNumber(value);
  206. AddOrReplace(m_json, key, val);
  207. return *this;
  208. }
  209. Document& Document::WithDouble(const Aws::String& key, double value)
  210. {
  211. return WithDouble(key.c_str(), value);
  212. }
  213. Document& Document::AsDouble(double value)
  214. {
  215. Destroy();
  216. m_json = cJSON_AS4CPP_CreateNumber(value);
  217. return *this;
  218. }
  219. Document& Document::WithArray(const char* key, const Array<Aws::String>& array)
  220. {
  221. if (!m_json)
  222. {
  223. m_json = cJSON_AS4CPP_CreateObject();
  224. }
  225. auto arrayValue = cJSON_AS4CPP_CreateArray();
  226. for (unsigned i = 0; i < array.GetLength(); ++i)
  227. {
  228. cJSON_AS4CPP_AddItemToArray(arrayValue, cJSON_AS4CPP_CreateString(array[i].c_str()));
  229. }
  230. AddOrReplace(m_json, key, arrayValue);
  231. return *this;
  232. }
  233. Document& Document::WithArray(const Aws::String& key, const Array<Aws::String>& array)
  234. {
  235. return WithArray(key.c_str(), array);
  236. }
  237. Document& Document::WithArray(const Aws::String& key, const Array<Document>& array)
  238. {
  239. if (!m_json)
  240. {
  241. m_json = cJSON_AS4CPP_CreateObject();
  242. }
  243. auto arrayValue = cJSON_AS4CPP_CreateArray();
  244. for (unsigned i = 0; i < array.GetLength(); ++i)
  245. {
  246. cJSON_AS4CPP_AddItemToArray(arrayValue, cJSON_AS4CPP_Duplicate(array[i].m_json, true /*recurse*/));
  247. }
  248. AddOrReplace(m_json, key.c_str(), arrayValue);
  249. return *this;
  250. }
  251. Document& Document::WithArray(const Aws::String& key, Array<Document>&& array)
  252. {
  253. if (!m_json)
  254. {
  255. m_json = cJSON_AS4CPP_CreateObject();
  256. }
  257. auto arrayValue = cJSON_AS4CPP_CreateArray();
  258. for (unsigned i = 0; i < array.GetLength(); ++i)
  259. {
  260. cJSON_AS4CPP_AddItemToArray(arrayValue, array[i].m_json);
  261. array[i].m_json = nullptr;
  262. }
  263. AddOrReplace(m_json, key.c_str(), arrayValue);
  264. return *this;
  265. }
  266. Document& Document::AsArray(const Array<Document>& array)
  267. {
  268. auto arrayValue = cJSON_AS4CPP_CreateArray();
  269. for (unsigned i = 0; i < array.GetLength(); ++i)
  270. {
  271. cJSON_AS4CPP_AddItemToArray(arrayValue, cJSON_AS4CPP_Duplicate(array[i].m_json, true /*recurse*/));
  272. }
  273. Destroy();
  274. m_json = arrayValue;
  275. return *this;
  276. }
  277. Document& Document::AsArray(Array<Document>&& array)
  278. {
  279. auto arrayValue = cJSON_AS4CPP_CreateArray();
  280. for (unsigned i = 0; i < array.GetLength(); ++i)
  281. {
  282. cJSON_AS4CPP_AddItemToArray(arrayValue, array[i].m_json);
  283. array[i].m_json = nullptr;
  284. }
  285. Destroy();
  286. m_json = arrayValue;
  287. return *this;
  288. }
  289. Document& Document::WithObject(const char* key, const Document& value)
  290. {
  291. if (!m_json)
  292. {
  293. m_json = cJSON_AS4CPP_CreateObject();
  294. }
  295. const auto copy = value.m_json == nullptr ? cJSON_AS4CPP_CreateObject() : cJSON_AS4CPP_Duplicate(value.m_json, true /*recurse*/);
  296. AddOrReplace(m_json, key, copy);
  297. return *this;
  298. }
  299. Document& Document::WithObject(const Aws::String& key, const Document& value)
  300. {
  301. return WithObject(key.c_str(), value);
  302. }
  303. Document& Document::WithObject(const char* key, Document&& value)
  304. {
  305. if (!m_json)
  306. {
  307. m_json = cJSON_AS4CPP_CreateObject();
  308. }
  309. AddOrReplace(m_json, key, value.m_json == nullptr ? cJSON_AS4CPP_CreateObject() : value.m_json);
  310. value.m_json = nullptr;
  311. return *this;
  312. }
  313. Document& Document::WithObject(const Aws::String& key, Document&& value)
  314. {
  315. return WithObject(key.c_str(), std::move(value));
  316. }
  317. Document& Document::AsObject(const Document& value)
  318. {
  319. *this = value;
  320. return *this;
  321. }
  322. Document& Document::AsObject(Document && value)
  323. {
  324. *this = std::move(value);
  325. return *this;
  326. }
  327. DocumentView Document::View() const
  328. {
  329. return *this;
  330. }
  331. DocumentView::DocumentView() : m_json(nullptr)
  332. {
  333. }
  334. DocumentView::DocumentView(const Document& value) : m_json(value.m_json)
  335. {
  336. }
  337. DocumentView::DocumentView(cJSON* v) : m_json(v)
  338. {
  339. }
  340. DocumentView& DocumentView::operator=(const Document& value)
  341. {
  342. m_json = value.m_json;
  343. return *this;
  344. }
  345. DocumentView& DocumentView::operator=(cJSON* value)
  346. {
  347. m_json = value;
  348. return *this;
  349. }
  350. Aws::String DocumentView::GetString(const Aws::String& key) const
  351. {
  352. assert(m_json);
  353. auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
  354. auto str = cJSON_AS4CPP_GetStringValue(item);
  355. return str ? str : "";
  356. }
  357. Aws::String DocumentView::AsString() const
  358. {
  359. const char* str = cJSON_AS4CPP_GetStringValue(m_json);
  360. if (str == nullptr)
  361. {
  362. return {};
  363. }
  364. return str;
  365. }
  366. bool DocumentView::IsString() const
  367. {
  368. return cJSON_AS4CPP_IsString(m_json) != 0;
  369. }
  370. bool DocumentView::GetBool(const Aws::String& key) const
  371. {
  372. assert(m_json);
  373. auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
  374. assert(item);
  375. return item->valueint != 0;
  376. }
  377. bool DocumentView::AsBool() const
  378. {
  379. assert(cJSON_AS4CPP_IsBool(m_json));
  380. return cJSON_AS4CPP_IsTrue(m_json) != 0;
  381. }
  382. bool DocumentView::IsBool() const
  383. {
  384. return cJSON_AS4CPP_IsBool(m_json) != 0;
  385. }
  386. int DocumentView::GetInteger(const Aws::String& key) const
  387. {
  388. assert(m_json);
  389. auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
  390. assert(item);
  391. return item->valueint;
  392. }
  393. int DocumentView::AsInteger() const
  394. {
  395. assert(cJSON_AS4CPP_IsNumber(m_json)); // can be double or value larger than int_max, but at least not UB
  396. return m_json->valueint;
  397. }
  398. bool DocumentView::IsIntegerType() const
  399. {
  400. if (!cJSON_AS4CPP_IsNumber(m_json))
  401. {
  402. return false;
  403. }
  404. if (m_json->valuestring)
  405. {
  406. Aws::String valueString = m_json->valuestring;
  407. return std::all_of(valueString.begin(), valueString.end(), [](unsigned char c){ return ::isdigit(c) || c == '+' || c == '-'; });
  408. }
  409. return m_json->valuedouble == static_cast<long long>(m_json->valuedouble);
  410. }
  411. int64_t DocumentView::GetInt64(const Aws::String& key) const
  412. {
  413. assert(m_json);
  414. auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
  415. assert(item);
  416. if (item->valuestring)
  417. {
  418. return Aws::Utils::StringUtils::ConvertToInt64(item->valuestring);
  419. }
  420. else
  421. {
  422. return static_cast<int64_t>(item->valuedouble);
  423. }
  424. }
  425. int64_t DocumentView::AsInt64() const
  426. {
  427. assert(cJSON_AS4CPP_IsNumber(m_json));
  428. if (m_json->valuestring)
  429. {
  430. return Aws::Utils::StringUtils::ConvertToInt64(m_json->valuestring);
  431. }
  432. else
  433. {
  434. return static_cast<int64_t>(m_json->valuedouble);
  435. }
  436. }
  437. double DocumentView::GetDouble(const Aws::String& key) const
  438. {
  439. assert(m_json);
  440. auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
  441. assert(item);
  442. return item->valuedouble;
  443. }
  444. double DocumentView::AsDouble() const
  445. {
  446. assert(cJSON_AS4CPP_IsNumber(m_json));
  447. return m_json->valuedouble;
  448. }
  449. bool DocumentView::IsFloatingPointType() const
  450. {
  451. if (!cJSON_AS4CPP_IsNumber(m_json))
  452. {
  453. return false;
  454. }
  455. if (m_json->valuestring)
  456. {
  457. Aws::String valueString = m_json->valuestring;
  458. return std::any_of(valueString.begin(), valueString.end(), [](unsigned char c){ return !::isdigit(c) && c != '+' && c != '-'; });
  459. }
  460. return m_json->valuedouble != static_cast<long long>(m_json->valuedouble);
  461. }
  462. Array<DocumentView> DocumentView::GetArray(const Aws::String& key) const
  463. {
  464. assert(m_json);
  465. auto array = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
  466. assert(cJSON_AS4CPP_IsArray(array));
  467. Array<DocumentView> returnArray(cJSON_AS4CPP_GetArraySize(array));
  468. auto element = array->child;
  469. for (unsigned i = 0; element && i < returnArray.GetLength(); ++i, element = element->next)
  470. {
  471. returnArray[i] = element;
  472. }
  473. return returnArray;
  474. }
  475. Array<DocumentView> DocumentView::AsArray() const
  476. {
  477. assert(cJSON_AS4CPP_IsArray(m_json));
  478. Array<DocumentView> returnArray(cJSON_AS4CPP_GetArraySize(m_json));
  479. auto element = m_json->child;
  480. for (unsigned i = 0; element && i < returnArray.GetLength(); ++i, element = element->next)
  481. {
  482. returnArray[i] = element;
  483. }
  484. return returnArray;
  485. }
  486. bool DocumentView::IsListType() const
  487. {
  488. return cJSON_AS4CPP_IsArray(m_json) != 0;
  489. }
  490. DocumentView DocumentView::GetObject(const Aws::String& key) const
  491. {
  492. assert(m_json);
  493. auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
  494. return item;
  495. }
  496. DocumentView DocumentView::AsObject() const
  497. {
  498. assert(cJSON_AS4CPP_IsObject(m_json) || cJSON_AS4CPP_IsNull(m_json));
  499. return m_json;
  500. }
  501. bool DocumentView::IsObject() const
  502. {
  503. return cJSON_AS4CPP_IsObject(m_json) != 0;
  504. }
  505. bool DocumentView::IsNull() const
  506. {
  507. return cJSON_AS4CPP_IsNull(m_json) != 0;
  508. }
  509. Aws::Map<Aws::String, DocumentView> DocumentView::GetAllObjects() const
  510. {
  511. Aws::Map<Aws::String, DocumentView> valueMap;
  512. if (!m_json)
  513. {
  514. return valueMap;
  515. }
  516. for (auto iter = m_json->child; iter; iter = iter->next)
  517. {
  518. valueMap.emplace(std::make_pair(Aws::String(iter->string), DocumentView(iter)));
  519. }
  520. return valueMap;
  521. }
  522. bool DocumentView::ValueExists(const Aws::String& key) const
  523. {
  524. if (!cJSON_AS4CPP_IsObject(m_json))
  525. {
  526. return false;
  527. }
  528. auto item = cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str());
  529. return !(item == nullptr || cJSON_AS4CPP_IsNull(item));
  530. }
  531. bool DocumentView::KeyExists(const Aws::String& key) const
  532. {
  533. if (!cJSON_AS4CPP_IsObject(m_json))
  534. {
  535. return false;
  536. }
  537. return cJSON_AS4CPP_GetObjectItemCaseSensitive(m_json, key.c_str()) != nullptr;;
  538. }
  539. Aws::String DocumentView::WriteCompact() const
  540. {
  541. if (!m_json)
  542. {
  543. return "null";
  544. }
  545. auto temp = cJSON_AS4CPP_PrintUnformatted(m_json);
  546. Aws::String out(temp);
  547. cJSON_AS4CPP_free(temp);
  548. return out;
  549. }
  550. Aws::String DocumentView::WriteReadable() const
  551. {
  552. if (!m_json)
  553. {
  554. return "null";
  555. }
  556. auto temp = cJSON_AS4CPP_Print(m_json);
  557. Aws::String out(temp);
  558. cJSON_AS4CPP_free(temp);
  559. return out;
  560. }
  561. Document DocumentView::Materialize() const
  562. {
  563. return m_json;
  564. }