json_value.cpp 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. #include "json_value.h"
  2. #include "json.h"
  3. #include <util/generic/ymath.h>
  4. #include <util/generic/ylimits.h>
  5. #include <util/generic/utility.h>
  6. #include <util/generic/singleton.h>
  7. #include <util/stream/str.h>
  8. #include <util/stream/output.h>
  9. #include <util/string/cast.h>
  10. #include <util/string/type.h>
  11. #include <util/string/vector.h>
  12. #include <util/system/yassert.h>
  13. #include <util/ysaveload.h>
  14. #include <util/generic/bt_exception.h>
  15. static bool
  16. AreJsonMapsEqual(const NJson::TJsonValue& lhs, const NJson::TJsonValue& rhs) {
  17. using namespace NJson;
  18. Y_ABORT_UNLESS(lhs.GetType() == JSON_MAP, "lhs has not a JSON_MAP type.");
  19. if (rhs.GetType() != JSON_MAP)
  20. return false;
  21. typedef TJsonValue::TMapType TMapType;
  22. const TMapType& lhsMap = lhs.GetMap();
  23. const TMapType& rhsMap = rhs.GetMap();
  24. if (lhsMap.size() != rhsMap.size())
  25. return false;
  26. for (const auto& lhsIt : lhsMap) {
  27. TMapType::const_iterator rhsIt = rhsMap.find(lhsIt.first);
  28. if (rhsIt == rhsMap.end())
  29. return false;
  30. if (lhsIt.second != rhsIt->second)
  31. return false;
  32. }
  33. return true;
  34. }
  35. static bool
  36. AreJsonArraysEqual(const NJson::TJsonValue& lhs, const NJson::TJsonValue& rhs) {
  37. using namespace NJson;
  38. Y_ABORT_UNLESS(lhs.GetType() == JSON_ARRAY, "lhs has not a JSON_ARRAY type.");
  39. if (rhs.GetType() != JSON_ARRAY)
  40. return false;
  41. typedef TJsonValue::TArray TArray;
  42. const TArray& lhsArray = lhs.GetArray();
  43. const TArray& rhsArray = rhs.GetArray();
  44. if (lhsArray.size() != rhsArray.size())
  45. return false;
  46. for (TArray::const_iterator lhsIt = lhsArray.begin(), rhsIt = rhsArray.begin();
  47. lhsIt != lhsArray.end(); ++lhsIt, ++rhsIt) {
  48. if (*lhsIt != *rhsIt)
  49. return false;
  50. }
  51. return true;
  52. }
  53. namespace NJson {
  54. const TJsonValue TJsonValue::UNDEFINED{};
  55. TJsonValue::TJsonValue(const EJsonValueType type) {
  56. SetType(type);
  57. }
  58. TJsonValue::TJsonValue(TJsonValue&& vval) noexcept
  59. : Type(JSON_UNDEFINED)
  60. {
  61. vval.SwapWithUndefined(*this);
  62. Zero(vval.Value);
  63. }
  64. TJsonValue::TJsonValue(const TJsonValue& val)
  65. : Type(val.Type)
  66. {
  67. switch (Type) {
  68. case JSON_STRING:
  69. new (&Value.String) TString(val.GetString());
  70. break;
  71. case JSON_MAP:
  72. Value.Map = new TMapType(val.GetMap());
  73. break;
  74. case JSON_ARRAY:
  75. Value.Array = new TArray(val.GetArray());
  76. break;
  77. case JSON_UNDEFINED:
  78. case JSON_NULL:
  79. case JSON_BOOLEAN:
  80. case JSON_INTEGER:
  81. case JSON_UINTEGER:
  82. case JSON_DOUBLE:
  83. std::memcpy(&Value, &val.Value, sizeof(Value));
  84. break;
  85. }
  86. }
  87. TJsonValue& TJsonValue::operator=(const TJsonValue& val) {
  88. if (this == &val)
  89. return *this;
  90. TJsonValue tmp(val);
  91. tmp.Swap(*this);
  92. return *this;
  93. }
  94. TJsonValue& TJsonValue::operator=(TJsonValue&& val) noexcept {
  95. if (this == &val)
  96. return *this;
  97. TJsonValue tmp(std::move(val));
  98. tmp.Swap(*this);
  99. return *this;
  100. }
  101. TJsonValue::TJsonValue(const bool value) noexcept {
  102. SetType(JSON_BOOLEAN);
  103. Value.Boolean = value;
  104. }
  105. TJsonValue::TJsonValue(const long long value) noexcept {
  106. SetType(JSON_INTEGER);
  107. Value.Integer = value;
  108. }
  109. TJsonValue::TJsonValue(const unsigned long long value) noexcept {
  110. SetType(JSON_UINTEGER);
  111. Value.UInteger = value;
  112. }
  113. TJsonValue::TJsonValue(const int value) noexcept {
  114. SetType(JSON_INTEGER);
  115. Value.Integer = value;
  116. }
  117. TJsonValue::TJsonValue(const unsigned int value) noexcept {
  118. SetType(JSON_UINTEGER);
  119. Value.UInteger = value;
  120. }
  121. TJsonValue::TJsonValue(const long value) noexcept {
  122. SetType(JSON_INTEGER);
  123. Value.Integer = value;
  124. }
  125. TJsonValue::TJsonValue(const unsigned long value) noexcept {
  126. SetType(JSON_UINTEGER);
  127. Value.UInteger = value;
  128. }
  129. TJsonValue::TJsonValue(const double value) noexcept {
  130. SetType(JSON_DOUBLE);
  131. Value.Double = value;
  132. }
  133. TJsonValue::TJsonValue(TString value) {
  134. SetType(JSON_STRING);
  135. Value.String = std::move(value);
  136. }
  137. TJsonValue::TJsonValue(const TStringBuf value) {
  138. SetType(JSON_STRING);
  139. Value.String = value;
  140. }
  141. TJsonValue::TJsonValue(const char* value) {
  142. SetType(JSON_STRING);
  143. Value.String = value;
  144. }
  145. EJsonValueType TJsonValue::GetType() const noexcept {
  146. return Type;
  147. }
  148. TJsonValue& TJsonValue::SetType(const EJsonValueType type) {
  149. if (Type == type)
  150. return *this;
  151. Clear();
  152. Type = type;
  153. switch (Type) {
  154. case JSON_STRING:
  155. new (&Value.String) TString();
  156. break;
  157. case JSON_MAP:
  158. Value.Map = new TMapType();
  159. break;
  160. case JSON_ARRAY:
  161. Value.Array = new TArray();
  162. break;
  163. case JSON_UNDEFINED:
  164. case JSON_NULL:
  165. case JSON_BOOLEAN:
  166. case JSON_INTEGER:
  167. case JSON_UINTEGER:
  168. case JSON_DOUBLE:
  169. break;
  170. }
  171. return *this;
  172. }
  173. TJsonValue& TJsonValue::SetValue(const TJsonValue& value) {
  174. return *this = value;
  175. }
  176. TJsonValue& TJsonValue::SetValue(TJsonValue&& value) {
  177. *this = std::move(value);
  178. return *this;
  179. }
  180. TJsonValue& TJsonValue::InsertValue(const TString& key, const TJsonValue& value) {
  181. SetType(JSON_MAP);
  182. return (*Value.Map)[key] = value;
  183. }
  184. TJsonValue& TJsonValue::InsertValue(const TStringBuf key, const TJsonValue& value) {
  185. SetType(JSON_MAP);
  186. return (*Value.Map)[key] = value;
  187. }
  188. TJsonValue& TJsonValue::InsertValue(const char* key, const TJsonValue& value) {
  189. SetType(JSON_MAP);
  190. return (*Value.Map)[key] = value;
  191. }
  192. TJsonValue& TJsonValue::InsertValue(const TString& key, TJsonValue&& value) {
  193. SetType(JSON_MAP);
  194. return (*Value.Map)[key] = std::move(value);
  195. }
  196. TJsonValue& TJsonValue::InsertValue(const TStringBuf key, TJsonValue&& value) {
  197. SetType(JSON_MAP);
  198. return (*Value.Map)[key] = std::move(value);
  199. }
  200. TJsonValue& TJsonValue::InsertValue(const char* key, TJsonValue&& value) {
  201. SetType(JSON_MAP);
  202. return (*Value.Map)[key] = std::move(value);
  203. }
  204. TJsonValue& TJsonValue::Back() {
  205. BackChecks();
  206. return Value.Array->back();
  207. }
  208. const TJsonValue& TJsonValue::Back() const {
  209. BackChecks();
  210. return Value.Array->back();
  211. }
  212. TJsonValue& TJsonValue::AppendValue(const TJsonValue& value) {
  213. SetType(JSON_ARRAY);
  214. Value.Array->push_back(value);
  215. return Value.Array->back();
  216. }
  217. TJsonValue& TJsonValue::AppendValue(TJsonValue&& value) {
  218. SetType(JSON_ARRAY);
  219. Value.Array->push_back(std::move(value));
  220. return Value.Array->back();
  221. }
  222. void TJsonValue::EraseValue(const TStringBuf key) {
  223. if (IsMap()) {
  224. TMapType::iterator it = Value.Map->find(key);
  225. if (it != Value.Map->end())
  226. Value.Map->erase(it);
  227. }
  228. }
  229. void TJsonValue::EraseValue(const size_t index) {
  230. if (IsArray()) {
  231. if (index >= Value.Array->size()) {
  232. return;
  233. }
  234. TArray::iterator it = Value.Array->begin() + index;
  235. Value.Array->erase(it);
  236. }
  237. }
  238. void TJsonValue::Clear() noexcept {
  239. switch (Type) {
  240. case JSON_STRING:
  241. Value.String.~TString();
  242. break;
  243. case JSON_MAP:
  244. delete Value.Map;
  245. break;
  246. case JSON_ARRAY:
  247. delete Value.Array;
  248. break;
  249. case JSON_UNDEFINED:
  250. case JSON_NULL:
  251. case JSON_BOOLEAN:
  252. case JSON_INTEGER:
  253. case JSON_UINTEGER:
  254. case JSON_DOUBLE:
  255. break;
  256. }
  257. Zero(Value);
  258. Type = JSON_UNDEFINED;
  259. }
  260. TJsonValue& TJsonValue::operator[](const size_t idx) {
  261. SetType(JSON_ARRAY);
  262. if (Value.Array->size() <= idx)
  263. Value.Array->resize(idx + 1);
  264. return (*Value.Array)[idx];
  265. }
  266. TJsonValue& TJsonValue::operator[](const TStringBuf& key) {
  267. SetType(JSON_MAP);
  268. return (*Value.Map)[key];
  269. }
  270. namespace {
  271. struct TDefaultsHolder {
  272. const TString String{};
  273. const TJsonValue::TMapType Map{};
  274. const TJsonValue::TArray Array{};
  275. const TJsonValue Value{};
  276. };
  277. }
  278. const TJsonValue& TJsonValue::operator[](const size_t idx) const noexcept {
  279. const TJsonValue* ret = nullptr;
  280. if (GetValuePointer(idx, &ret))
  281. return *ret;
  282. return Singleton<TDefaultsHolder>()->Value;
  283. }
  284. const TJsonValue& TJsonValue::operator[](const TStringBuf& key) const noexcept {
  285. const TJsonValue* ret = nullptr;
  286. if (GetValuePointer(key, &ret))
  287. return *ret;
  288. return Singleton<TDefaultsHolder>()->Value;
  289. }
  290. bool TJsonValue::GetBoolean() const {
  291. return Type != JSON_BOOLEAN ? false : Value.Boolean;
  292. }
  293. long long TJsonValue::GetInteger() const {
  294. if (!IsInteger())
  295. return 0;
  296. switch (Type) {
  297. case JSON_INTEGER:
  298. return Value.Integer;
  299. case JSON_UINTEGER:
  300. return Value.UInteger;
  301. case JSON_DOUBLE:
  302. return Value.Double;
  303. default:
  304. Y_ASSERT(false && "Unexpected type.");
  305. return 0;
  306. }
  307. }
  308. unsigned long long TJsonValue::GetUInteger() const {
  309. if (!IsUInteger())
  310. return 0;
  311. switch (Type) {
  312. case JSON_UINTEGER:
  313. return Value.UInteger;
  314. case JSON_INTEGER:
  315. return Value.Integer;
  316. case JSON_DOUBLE:
  317. return Value.Double;
  318. default:
  319. Y_ASSERT(false && "Unexpected type.");
  320. return 0;
  321. }
  322. }
  323. double TJsonValue::GetDouble() const {
  324. if (!IsDouble())
  325. return 0.0;
  326. switch (Type) {
  327. case JSON_DOUBLE:
  328. return Value.Double;
  329. case JSON_INTEGER:
  330. return Value.Integer;
  331. case JSON_UINTEGER:
  332. return Value.UInteger;
  333. default:
  334. Y_ASSERT(false && "Unexpected type.");
  335. return 0.0;
  336. }
  337. }
  338. const TString& TJsonValue::GetString() const {
  339. return Type != JSON_STRING ? Singleton<TDefaultsHolder>()->String : Value.String;
  340. }
  341. const TJsonValue::TMapType& TJsonValue::GetMap() const {
  342. return Type != JSON_MAP ? Singleton<TDefaultsHolder>()->Map : *Value.Map;
  343. }
  344. const TJsonValue::TArray& TJsonValue::GetArray() const {
  345. return (Type != JSON_ARRAY) ? Singleton<TDefaultsHolder>()->Array : *Value.Array;
  346. }
  347. bool TJsonValue::GetBooleanSafe() const {
  348. if (Type != JSON_BOOLEAN)
  349. ythrow TJsonException() << "Not a boolean";
  350. return Value.Boolean;
  351. }
  352. long long TJsonValue::GetIntegerSafe() const {
  353. if (!IsInteger())
  354. ythrow TJsonException() << "Not an integer";
  355. return GetInteger();
  356. }
  357. unsigned long long TJsonValue::GetUIntegerSafe() const {
  358. if (!IsUInteger())
  359. ythrow TJsonException() << "Not an unsigned integer";
  360. return GetUInteger();
  361. }
  362. double TJsonValue::GetDoubleSafe() const {
  363. if (!IsDouble())
  364. ythrow TJsonException() << "Not a double";
  365. return GetDouble();
  366. }
  367. const TString& TJsonValue::GetStringSafe() const {
  368. if (Type != JSON_STRING)
  369. ythrow TJsonException() << "Not a string";
  370. return Value.String;
  371. }
  372. bool TJsonValue::GetBooleanSafe(const bool defaultValue) const {
  373. if (Type == JSON_UNDEFINED)
  374. return defaultValue;
  375. return GetBooleanSafe();
  376. }
  377. long long TJsonValue::GetIntegerSafe(const long long defaultValue) const {
  378. if (Type == JSON_UNDEFINED)
  379. return defaultValue;
  380. return GetIntegerSafe();
  381. }
  382. unsigned long long TJsonValue::GetUIntegerSafe(const unsigned long long defaultValue) const {
  383. if (Type == JSON_UNDEFINED)
  384. return defaultValue;
  385. return GetUIntegerSafe();
  386. }
  387. double TJsonValue::GetDoubleSafe(const double defaultValue) const {
  388. if (Type == JSON_UNDEFINED)
  389. return defaultValue;
  390. return GetDoubleSafe();
  391. }
  392. TString TJsonValue::GetStringSafe(const TString& defaultValue) const {
  393. if (Type == JSON_UNDEFINED)
  394. return defaultValue;
  395. return GetStringSafe();
  396. }
  397. const TJsonValue::TMapType& TJsonValue::GetMapSafe() const {
  398. if (Type != JSON_MAP)
  399. ythrow TJsonException() << "Not a map";
  400. return *Value.Map;
  401. }
  402. TJsonValue::TMapType& TJsonValue::GetMapSafe() {
  403. return const_cast<TJsonValue::TMapType&>(const_cast<const TJsonValue*>(this)->GetMapSafe());
  404. }
  405. const TJsonValue::TArray& TJsonValue::GetArraySafe() const {
  406. if (Type != JSON_ARRAY)
  407. ythrow TJsonException() << "Not an array";
  408. return *Value.Array;
  409. }
  410. TJsonValue::TArray& TJsonValue::GetArraySafe() {
  411. return const_cast<TJsonValue::TArray&>(const_cast<const TJsonValue*>(this)->GetArraySafe());
  412. }
  413. bool TJsonValue::GetBooleanRobust() const noexcept {
  414. switch (Type) {
  415. case JSON_ARRAY:
  416. return !Value.Array->empty();
  417. case JSON_MAP:
  418. return !Value.Map->empty();
  419. case JSON_INTEGER:
  420. case JSON_UINTEGER:
  421. case JSON_DOUBLE:
  422. return GetIntegerRobust();
  423. case JSON_STRING:
  424. return GetIntegerRobust() || IsTrue(Value.String);
  425. case JSON_NULL:
  426. case JSON_UNDEFINED:
  427. default:
  428. return false;
  429. case JSON_BOOLEAN:
  430. return Value.Boolean;
  431. }
  432. }
  433. long long TJsonValue::GetIntegerRobust() const noexcept {
  434. switch (Type) {
  435. case JSON_ARRAY:
  436. return Value.Array->size();
  437. case JSON_MAP:
  438. return Value.Map->size();
  439. case JSON_BOOLEAN:
  440. return Value.Boolean;
  441. case JSON_DOUBLE:
  442. return GetDoubleRobust();
  443. case JSON_STRING:
  444. try {
  445. i64 res = 0;
  446. if (Value.String && TryFromString(Value.String, res)) {
  447. return res;
  448. }
  449. } catch (const yexception&) {
  450. }
  451. return 0;
  452. case JSON_NULL:
  453. case JSON_UNDEFINED:
  454. default:
  455. return 0;
  456. case JSON_INTEGER:
  457. case JSON_UINTEGER:
  458. return Value.Integer;
  459. }
  460. }
  461. unsigned long long TJsonValue::GetUIntegerRobust() const noexcept {
  462. switch (Type) {
  463. case JSON_ARRAY:
  464. return Value.Array->size();
  465. case JSON_MAP:
  466. return Value.Map->size();
  467. case JSON_BOOLEAN:
  468. return Value.Boolean;
  469. case JSON_DOUBLE:
  470. return GetDoubleRobust();
  471. case JSON_STRING:
  472. try {
  473. ui64 res = 0;
  474. if (Value.String && TryFromString(Value.String, res)) {
  475. return res;
  476. }
  477. } catch (const yexception&) {
  478. }
  479. return 0;
  480. case JSON_NULL:
  481. case JSON_UNDEFINED:
  482. default:
  483. return 0;
  484. case JSON_INTEGER:
  485. case JSON_UINTEGER:
  486. return Value.UInteger;
  487. }
  488. }
  489. double TJsonValue::GetDoubleRobust() const noexcept {
  490. switch (Type) {
  491. case JSON_ARRAY:
  492. return Value.Array->size();
  493. case JSON_MAP:
  494. return Value.Map->size();
  495. case JSON_BOOLEAN:
  496. return Value.Boolean;
  497. case JSON_INTEGER:
  498. return Value.Integer;
  499. case JSON_UINTEGER:
  500. return Value.UInteger;
  501. case JSON_STRING:
  502. try {
  503. double res = 0;
  504. if (Value.String && TryFromString(Value.String, res)) {
  505. return res;
  506. }
  507. } catch (const yexception&) {
  508. }
  509. return 0;
  510. case JSON_NULL:
  511. case JSON_UNDEFINED:
  512. default:
  513. return 0;
  514. case JSON_DOUBLE:
  515. return Value.Double;
  516. }
  517. }
  518. TString TJsonValue::GetStringRobust() const {
  519. switch (Type) {
  520. case JSON_ARRAY:
  521. case JSON_MAP:
  522. case JSON_BOOLEAN:
  523. case JSON_DOUBLE:
  524. case JSON_INTEGER:
  525. case JSON_UINTEGER:
  526. case JSON_NULL:
  527. case JSON_UNDEFINED:
  528. default: {
  529. NJsonWriter::TBuf sout;
  530. sout.WriteJsonValue(this);
  531. return sout.Str();
  532. }
  533. case JSON_STRING:
  534. return Value.String;
  535. }
  536. }
  537. bool TJsonValue::GetBoolean(bool* value) const noexcept {
  538. if (Type != JSON_BOOLEAN)
  539. return false;
  540. *value = Value.Boolean;
  541. return true;
  542. }
  543. bool TJsonValue::GetInteger(long long* value) const noexcept {
  544. if (!IsInteger())
  545. return false;
  546. *value = GetInteger();
  547. return true;
  548. }
  549. bool TJsonValue::GetUInteger(unsigned long long* value) const noexcept {
  550. if (!IsUInteger())
  551. return false;
  552. *value = GetUInteger();
  553. return true;
  554. }
  555. bool TJsonValue::GetDouble(double* value) const noexcept {
  556. if (!IsDouble())
  557. return false;
  558. *value = GetDouble();
  559. return true;
  560. }
  561. bool TJsonValue::GetString(TString* value) const {
  562. if (Type != JSON_STRING)
  563. return false;
  564. *value = Value.String;
  565. return true;
  566. }
  567. bool TJsonValue::GetMap(TJsonValue::TMapType* value) const {
  568. if (Type != JSON_MAP)
  569. return false;
  570. *value = *Value.Map;
  571. return true;
  572. }
  573. bool TJsonValue::GetArray(TJsonValue::TArray* value) const {
  574. if (Type != JSON_ARRAY)
  575. return false;
  576. *value = *Value.Array;
  577. return true;
  578. }
  579. bool TJsonValue::GetMapPointer(const TJsonValue::TMapType** value) const noexcept {
  580. if (Type != JSON_MAP)
  581. return false;
  582. *value = Value.Map;
  583. return true;
  584. }
  585. bool TJsonValue::GetArrayPointer(const TJsonValue::TArray** value) const noexcept {
  586. if (Type != JSON_ARRAY)
  587. return false;
  588. *value = Value.Array;
  589. return true;
  590. }
  591. bool TJsonValue::GetValue(const size_t index, TJsonValue* value) const {
  592. const TJsonValue* tmp = nullptr;
  593. if (GetValuePointer(index, &tmp)) {
  594. *value = *tmp;
  595. return true;
  596. }
  597. return false;
  598. }
  599. bool TJsonValue::GetValue(const TStringBuf key, TJsonValue* value) const {
  600. const TJsonValue* tmp = nullptr;
  601. if (GetValuePointer(key, &tmp)) {
  602. *value = *tmp;
  603. return true;
  604. }
  605. return false;
  606. }
  607. bool TJsonValue::GetValuePointer(const size_t index, const TJsonValue** value) const noexcept {
  608. if (Type == JSON_ARRAY && index < Value.Array->size()) {
  609. *value = &(*Value.Array)[index];
  610. return true;
  611. }
  612. return false;
  613. }
  614. bool TJsonValue::GetValuePointer(const TStringBuf key, const TJsonValue** value) const noexcept {
  615. if (Type == JSON_MAP) {
  616. const TMapType::const_iterator it = Value.Map->find(key);
  617. if (it != Value.Map->end()) {
  618. *value = &(it->second);
  619. return true;
  620. }
  621. }
  622. return false;
  623. }
  624. bool TJsonValue::GetValuePointer(const TStringBuf key, TJsonValue** value) noexcept {
  625. return static_cast<const TJsonValue*>(this)->GetValuePointer(key, const_cast<const TJsonValue**>(value));
  626. }
  627. bool TJsonValue::IsNull() const noexcept {
  628. return Type == JSON_NULL;
  629. }
  630. bool TJsonValue::IsBoolean() const noexcept {
  631. return Type == JSON_BOOLEAN;
  632. }
  633. bool TJsonValue::IsInteger() const noexcept {
  634. switch (Type) {
  635. case JSON_INTEGER:
  636. return true;
  637. case JSON_UINTEGER:
  638. return (Value.UInteger <= static_cast<unsigned long long>(Max<long long>()));
  639. case JSON_DOUBLE:
  640. return ((long long)Value.Double == Value.Double);
  641. default:
  642. return false;
  643. }
  644. }
  645. bool TJsonValue::IsUInteger() const noexcept {
  646. switch (Type) {
  647. case JSON_UINTEGER:
  648. return true;
  649. case JSON_INTEGER:
  650. return (Value.Integer >= 0);
  651. case JSON_DOUBLE:
  652. return ((unsigned long long)Value.Double == Value.Double);
  653. default:
  654. return false;
  655. }
  656. }
  657. bool TJsonValue::IsDouble() const noexcept {
  658. // Check whether we can convert integer to floating-point
  659. // without precision loss.
  660. switch (Type) {
  661. case JSON_DOUBLE:
  662. return true;
  663. case JSON_INTEGER:
  664. return (1ll << std::numeric_limits<double>::digits) >= Abs(Value.Integer);
  665. case JSON_UINTEGER:
  666. return (1ull << std::numeric_limits<double>::digits) >= Value.UInteger;
  667. default:
  668. return false;
  669. }
  670. }
  671. namespace {
  672. template <class TPtr, class T>
  673. TPtr* CreateOrNullptr(TPtr* p, T key, std::true_type /*create*/) {
  674. return &(*p)[key];
  675. }
  676. template <class TPtr, class T>
  677. TPtr* CreateOrNullptr(const TPtr* p, T key, std::false_type /*create*/) noexcept {
  678. const TPtr* const next = &(*p)[key];
  679. return next->IsDefined() ? const_cast<TPtr*>(next) : nullptr;
  680. }
  681. template <bool Create, class TJsonPtr>
  682. TJsonPtr GetValuePtrByPath(TJsonPtr currentJson, TStringBuf path, char delimiter) noexcept(!Create) {
  683. static_assert(
  684. !(Create && std::is_const<std::remove_pointer_t<TJsonPtr>>::value),
  685. "TJsonPtr must be a `TJsonValue*` if `Create` is true");
  686. constexpr std::integral_constant<bool, Create> create_tag{};
  687. while (!path.empty()) {
  688. size_t index = 0;
  689. const TStringBuf step = path.NextTok(delimiter);
  690. if (step.size() > 2 && *step.begin() == '[' && step.back() == ']' && TryFromString(step.substr(1, step.size() - 2), index)) {
  691. currentJson = CreateOrNullptr(currentJson, index, create_tag);
  692. } else {
  693. currentJson = CreateOrNullptr(currentJson, step, create_tag);
  694. }
  695. if (!currentJson) {
  696. return nullptr;
  697. }
  698. }
  699. return currentJson;
  700. }
  701. } // anonymous namespace
  702. bool TJsonValue::GetValueByPath(const TStringBuf path, TJsonValue& result, char delimiter) const {
  703. const TJsonValue* const ptr = GetValuePtrByPath<false>(this, path, delimiter);
  704. if (ptr) {
  705. result = *ptr;
  706. return true;
  707. }
  708. return false;
  709. }
  710. bool TJsonValue::SetValueByPath(const TStringBuf path, const TJsonValue& value, char delimiter) {
  711. TJsonValue* const ptr = GetValuePtrByPath<true>(this, path, delimiter);
  712. if (ptr) {
  713. *ptr = value;
  714. return true;
  715. }
  716. return false;
  717. }
  718. bool TJsonValue::SetValueByPath(const TStringBuf path, TJsonValue&& value, char delimiter) {
  719. TJsonValue* const ptr = GetValuePtrByPath<true>(this, path, delimiter);
  720. if (ptr) {
  721. *ptr = std::move(value);
  722. return true;
  723. }
  724. return false;
  725. }
  726. const TJsonValue* TJsonValue::GetValueByPath(const TStringBuf key, char delim) const noexcept {
  727. return GetValuePtrByPath<false>(this, key, delim);
  728. }
  729. TJsonValue* TJsonValue::GetValueByPath(const TStringBuf key, char delim) noexcept {
  730. return GetValuePtrByPath<false>(this, key, delim);
  731. }
  732. void TJsonValue::DoScan(const TString& path, TJsonValue* parent, IScanCallback& callback) {
  733. if (!callback.Do(path, parent, *this)) {
  734. return;
  735. }
  736. if (Type == JSON_MAP) {
  737. for (auto&& i : *Value.Map) {
  738. i.second.DoScan(!!path ? TString::Join(path, ".", i.first) : i.first, this, callback);
  739. }
  740. } else if (Type == JSON_ARRAY) {
  741. for (ui32 i = 0; i < Value.Array->size(); ++i) {
  742. (*Value.Array)[i].DoScan(TString::Join(path, "[", ToString(i), "]"), this, callback);
  743. }
  744. }
  745. }
  746. void TJsonValue::Scan(IScanCallback& callback) {
  747. DoScan("", nullptr, callback);
  748. }
  749. bool TJsonValue::IsString() const noexcept {
  750. return Type == JSON_STRING;
  751. }
  752. bool TJsonValue::IsMap() const noexcept {
  753. return Type == JSON_MAP;
  754. }
  755. bool TJsonValue::IsArray() const noexcept {
  756. return Type == JSON_ARRAY;
  757. }
  758. bool TJsonValue::Has(const TStringBuf& key) const noexcept {
  759. return Type == JSON_MAP && Value.Map->contains(key);
  760. }
  761. bool TJsonValue::Has(size_t key) const noexcept {
  762. return Type == JSON_ARRAY && Value.Array->size() > key;
  763. }
  764. bool TJsonValue::operator==(const TJsonValue& rhs) const {
  765. switch (Type) {
  766. case JSON_UNDEFINED: {
  767. return (rhs.GetType() == JSON_UNDEFINED);
  768. }
  769. case JSON_NULL: {
  770. return rhs.IsNull();
  771. }
  772. case JSON_BOOLEAN: {
  773. return (rhs.IsBoolean() && Value.Boolean == rhs.Value.Boolean);
  774. }
  775. case JSON_INTEGER: {
  776. return (rhs.IsInteger() && GetInteger() == rhs.GetInteger());
  777. }
  778. case JSON_UINTEGER: {
  779. return (rhs.IsUInteger() && GetUInteger() == rhs.GetUInteger());
  780. }
  781. case JSON_STRING: {
  782. return (rhs.IsString() && Value.String == rhs.Value.String);
  783. }
  784. case JSON_DOUBLE: {
  785. return (rhs.IsDouble() && fabs(GetDouble() - rhs.GetDouble()) <= FLT_EPSILON);
  786. }
  787. case JSON_MAP:
  788. return AreJsonMapsEqual(*this, rhs);
  789. case JSON_ARRAY:
  790. return AreJsonArraysEqual(*this, rhs);
  791. default:
  792. Y_ASSERT(false && "Unknown type.");
  793. return false;
  794. }
  795. }
  796. void TJsonValue::SwapWithUndefined(TJsonValue& output) noexcept {
  797. if (Type == JSON_STRING) {
  798. static_assert(std::is_nothrow_move_constructible<TString>::value, "noexcept violation! Add some try {} catch (...) logic");
  799. new (&output.Value.String) TString(std::move(Value.String));
  800. Value.String.~TString();
  801. } else {
  802. std::memcpy(&output.Value, &Value, sizeof(Value));
  803. }
  804. output.Type = Type;
  805. Type = JSON_UNDEFINED;
  806. }
  807. void TJsonValue::Swap(TJsonValue& rhs) noexcept {
  808. TJsonValue tmp(std::move(*this));
  809. rhs.SwapWithUndefined(*this);
  810. tmp.SwapWithUndefined(rhs);
  811. }
  812. void TJsonValue::Save(IOutputStream* s) const {
  813. ::Save(s, static_cast<ui8>(Type));
  814. switch (Type) {
  815. case JSON_UNDEFINED:break;
  816. case JSON_NULL:break;
  817. case JSON_BOOLEAN:
  818. ::Save(s, Value.Boolean);
  819. break;
  820. case JSON_INTEGER:
  821. ::Save(s, Value.Integer);
  822. break;
  823. case JSON_UINTEGER:
  824. ::Save(s, Value.UInteger);
  825. break;
  826. case JSON_DOUBLE:
  827. ::Save(s, Value.Double);
  828. break;
  829. case JSON_STRING:
  830. ::Save(s, Value.String);
  831. break;
  832. case JSON_MAP:
  833. ::Save(s, *Value.Map);
  834. break;
  835. case JSON_ARRAY:
  836. ::Save(s, *Value.Array);
  837. break;
  838. }
  839. }
  840. void TJsonValue::Load(IInputStream* s) {
  841. {
  842. ui8 loadedType = {};
  843. ::Load(s, loadedType);
  844. SetType(static_cast<EJsonValueType>(loadedType));
  845. }
  846. switch (Type) {
  847. case JSON_UNDEFINED:break;
  848. case JSON_NULL:break;
  849. case JSON_BOOLEAN:
  850. ::Load(s, Value.Boolean);
  851. break;
  852. case JSON_INTEGER:
  853. ::Load(s, Value.Integer);
  854. break;
  855. case JSON_UINTEGER:
  856. ::Load(s, Value.UInteger);
  857. break;
  858. case JSON_DOUBLE:
  859. ::Load(s, Value.Double);
  860. break;
  861. case JSON_STRING:
  862. ::Load(s, Value.String);
  863. break;
  864. case JSON_MAP:
  865. ::Load(s, *Value.Map);
  866. break;
  867. case JSON_ARRAY:
  868. ::Load(s, *Value.Array);
  869. break;
  870. }
  871. }
  872. //****************************************************************
  873. bool GetMapPointer(const TJsonValue& jv, const size_t index, const TJsonValue::TMapType** value) {
  874. const TJsonValue* v;
  875. if (!jv.GetValuePointer(index, &v) || !v->IsMap())
  876. return false;
  877. *value = &v->GetMap();
  878. return true;
  879. }
  880. bool GetArrayPointer(const TJsonValue& jv, const size_t index, const TJsonValue::TArray** value) {
  881. const TJsonValue* v;
  882. if (!jv.GetValuePointer(index, &v) || !v->IsArray())
  883. return false;
  884. *value = &v->GetArray();
  885. return true;
  886. }
  887. bool GetMapPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TMapType** value) {
  888. const TJsonValue* v;
  889. if (!jv.GetValuePointer(key, &v) || !v->IsMap())
  890. return false;
  891. *value = &v->GetMap();
  892. return true;
  893. }
  894. bool GetArrayPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TArray** value) {
  895. const TJsonValue* v;
  896. if (!jv.GetValuePointer(key, &v) || !v->IsArray())
  897. return false;
  898. *value = &v->GetArray();
  899. return true;
  900. }
  901. void TJsonValue::BackChecks() const {
  902. if (Type != JSON_ARRAY)
  903. ythrow TJsonException() << "Not an array";
  904. if (Value.Array->empty())
  905. ythrow TJsonException() << "Get back on empty array";
  906. }
  907. }
  908. template <>
  909. void Out<NJson::TJsonValue>(IOutputStream& out, const NJson::TJsonValue& v) {
  910. NJsonWriter::TBuf buf(NJsonWriter::HEM_DONT_ESCAPE_HTML, &out);
  911. buf.WriteJsonValue(&v);
  912. }