json_reader_ut.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. #include <library/cpp/json/json_reader.h>
  2. #include <library/cpp/json/json_writer.h>
  3. #include <library/cpp/testing/unittest/registar.h>
  4. #include <util/stream/str.h>
  5. using namespace NJson;
  6. class TReformatCallbacks: public TJsonCallbacks {
  7. TJsonWriter& Writer;
  8. public:
  9. TReformatCallbacks(TJsonWriter& writer)
  10. : Writer(writer)
  11. {
  12. }
  13. bool OnBoolean(bool val) override {
  14. Writer.Write(val);
  15. return true;
  16. }
  17. bool OnInteger(long long val) override {
  18. Writer.Write(val);
  19. return true;
  20. }
  21. bool OnUInteger(unsigned long long val) override {
  22. Writer.Write(val);
  23. return true;
  24. }
  25. bool OnString(const TStringBuf& val) override {
  26. Writer.Write(val);
  27. return true;
  28. }
  29. bool OnDouble(double val) override {
  30. Writer.Write(val);
  31. return true;
  32. }
  33. bool OnOpenArray() override {
  34. Writer.OpenArray();
  35. return true;
  36. }
  37. bool OnCloseArray() override {
  38. Writer.CloseArray();
  39. return true;
  40. }
  41. bool OnOpenMap() override {
  42. Writer.OpenArray();
  43. return true;
  44. }
  45. bool OnCloseMap() override {
  46. Writer.CloseArray();
  47. return true;
  48. }
  49. bool OnMapKey(const TStringBuf& val) override {
  50. Writer.Write(val);
  51. return true;
  52. }
  53. };
  54. void GenerateDeepJsonArray(TStringStream& stream, ui64 depth) {
  55. stream << "{\"key\":";
  56. for (ui32 i = 0; i < depth - 1; ++i) {
  57. stream << "[";
  58. }
  59. for (ui32 i = 0; i < depth - 1; ++i) {
  60. stream << "]";
  61. }
  62. stream << "}";
  63. }
  64. void GenerateDeepJsonDict(TStringStream& stream, ui64 depth) {
  65. for (ui64 i = 0; i < depth - 1; ++i) {
  66. stream << "{\"key\":";
  67. }
  68. stream << "{}";
  69. for (ui64 i = 0; i < depth - 1; ++i) {
  70. stream << "}";
  71. }
  72. }
  73. Y_UNIT_TEST_SUITE(TJsonReaderTest) {
  74. Y_UNIT_TEST(JsonReformatTest) {
  75. TString data = "{\"null value\": null, \"intkey\": 10, \"double key\": 11.11, \"string key\": \"string\", \"array\": [1,2,3,\"TString\"], \"bool key\": true}";
  76. TString result1, result2;
  77. {
  78. TStringStream in;
  79. in << data;
  80. TStringStream out;
  81. TJsonWriter writer(&out, false);
  82. TReformatCallbacks cb(writer);
  83. ReadJson(&in, &cb);
  84. writer.Flush();
  85. result1 = out.Str();
  86. }
  87. {
  88. TStringStream in;
  89. in << result1;
  90. TStringStream out;
  91. TJsonWriter writer(&out, false);
  92. TReformatCallbacks cb(writer);
  93. ReadJson(&in, &cb);
  94. writer.Flush();
  95. result2 = out.Str();
  96. }
  97. UNIT_ASSERT_VALUES_EQUAL(result1, result2);
  98. }
  99. Y_UNIT_TEST(TJsonEscapedApostrophe) {
  100. TString jsonString = "{ \"foo\" : \"bar\\'buzz\" }";
  101. {
  102. TStringStream in;
  103. in << jsonString;
  104. TStringStream out;
  105. TJsonWriter writer(&out, false);
  106. TReformatCallbacks cb(writer);
  107. UNIT_ASSERT(!ReadJson(&in, &cb));
  108. }
  109. {
  110. TStringStream in;
  111. in << jsonString;
  112. TStringStream out;
  113. TJsonWriter writer(&out, false);
  114. TReformatCallbacks cb(writer);
  115. UNIT_ASSERT(ReadJson(&in, false, true, &cb));
  116. writer.Flush();
  117. UNIT_ASSERT_EQUAL(out.Str(), "[\"foo\",\"bar'buzz\"]");
  118. }
  119. }
  120. Y_UNIT_TEST(TJsonTreeTest) {
  121. TString data = "{\"intkey\": 10, \"double key\": 11.11, \"null value\":null, \"string key\": \"string\", \"array\": [1,2,3,\"TString\"], \"bool key\": true}";
  122. TStringStream in;
  123. in << data;
  124. TJsonValue value;
  125. ReadJsonTree(&in, &value);
  126. UNIT_ASSERT_VALUES_EQUAL(value["intkey"].GetInteger(), 10);
  127. UNIT_ASSERT_DOUBLES_EQUAL(value["double key"].GetDouble(), 11.11, 0.001);
  128. UNIT_ASSERT_VALUES_EQUAL(value["bool key"].GetBoolean(), true);
  129. UNIT_ASSERT_VALUES_EQUAL(value["absent string key"].GetString(), TString(""));
  130. UNIT_ASSERT_VALUES_EQUAL(value["string key"].GetString(), TString("string"));
  131. UNIT_ASSERT_VALUES_EQUAL(value["array"][0].GetInteger(), 1);
  132. UNIT_ASSERT_VALUES_EQUAL(value["array"][1].GetInteger(), 2);
  133. UNIT_ASSERT_VALUES_EQUAL(value["array"][2].GetInteger(), 3);
  134. UNIT_ASSERT_VALUES_EQUAL(value["array"][3].GetString(), TString("TString"));
  135. UNIT_ASSERT(value["null value"].IsNull());
  136. // AsString
  137. UNIT_ASSERT_VALUES_EQUAL(value["intkey"].GetStringRobust(), "10");
  138. UNIT_ASSERT_VALUES_EQUAL(value["double key"].GetStringRobust(), "11.11");
  139. UNIT_ASSERT_VALUES_EQUAL(value["bool key"].GetStringRobust(), "true");
  140. UNIT_ASSERT_VALUES_EQUAL(value["string key"].GetStringRobust(), "string");
  141. UNIT_ASSERT_VALUES_EQUAL(value["array"].GetStringRobust(), "[1,2,3,\"TString\"]");
  142. UNIT_ASSERT_VALUES_EQUAL(value["null value"].GetStringRobust(), "null");
  143. const TJsonValue::TArray* array;
  144. UNIT_ASSERT(GetArrayPointer(value, "array", &array));
  145. UNIT_ASSERT_VALUES_EQUAL(value["array"].GetArray().size(), array->size());
  146. UNIT_ASSERT_VALUES_EQUAL(value["array"][0].GetInteger(), (*array)[0].GetInteger());
  147. UNIT_ASSERT_VALUES_EQUAL(value["array"][1].GetInteger(), (*array)[1].GetInteger());
  148. UNIT_ASSERT_VALUES_EQUAL(value["array"][2].GetInteger(), (*array)[2].GetInteger());
  149. UNIT_ASSERT_VALUES_EQUAL(value["array"][3].GetString(), (*array)[3].GetString());
  150. }
  151. Y_UNIT_TEST(TJsonRomaTest) {
  152. TString data = "{\"test\": [ {\"name\": \"A\"} ]}";
  153. TStringStream in;
  154. in << data;
  155. TJsonValue value;
  156. ReadJsonTree(&in, &value);
  157. UNIT_ASSERT_VALUES_EQUAL(value["test"][0]["name"].GetString(), TString("A"));
  158. }
  159. Y_UNIT_TEST(TJsonReadTreeWithComments) {
  160. {
  161. TString leadingCommentData = "{ // \"test\" : 1 \n}";
  162. {
  163. // No comments allowed
  164. TStringStream in;
  165. in << leadingCommentData;
  166. TJsonValue value;
  167. UNIT_ASSERT(!ReadJsonTree(&in, false, &value));
  168. }
  169. {
  170. // Comments allowed
  171. TStringStream in;
  172. in << leadingCommentData;
  173. TJsonValue value;
  174. UNIT_ASSERT(ReadJsonTree(&in, true, &value));
  175. UNIT_ASSERT(!value.Has("test"));
  176. }
  177. }
  178. {
  179. TString trailingCommentData = "{ \"test1\" : 1 // \"test2\" : 2 \n }";
  180. {
  181. // No comments allowed
  182. TStringStream in;
  183. in << trailingCommentData;
  184. TJsonValue value;
  185. UNIT_ASSERT(!ReadJsonTree(&in, false, &value));
  186. }
  187. {
  188. // Comments allowed
  189. TStringStream in;
  190. in << trailingCommentData;
  191. TJsonValue value;
  192. UNIT_ASSERT(ReadJsonTree(&in, true, &value));
  193. UNIT_ASSERT(value.Has("test1"));
  194. UNIT_ASSERT_EQUAL(value["test1"].GetInteger(), 1);
  195. UNIT_ASSERT(!value.Has("test2"));
  196. }
  197. }
  198. }
  199. Y_UNIT_TEST(TJsonSignedIntegerTest) {
  200. {
  201. TStringStream in;
  202. in << "{ \"test\" : " << Min<i64>() << " }";
  203. TJsonValue value;
  204. UNIT_ASSERT(ReadJsonTree(&in, &value));
  205. UNIT_ASSERT(value.Has("test"));
  206. UNIT_ASSERT(value["test"].IsInteger());
  207. UNIT_ASSERT(!value["test"].IsUInteger());
  208. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), Min<i64>());
  209. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), Min<i64>());
  210. } // Min<i64>()
  211. {
  212. TStringStream in;
  213. in << "{ \"test\" : " << Max<i64>() + 1ull << " }";
  214. TJsonValue value;
  215. UNIT_ASSERT(ReadJsonTree(&in, &value));
  216. UNIT_ASSERT(value.Has("test"));
  217. UNIT_ASSERT(!value["test"].IsInteger());
  218. UNIT_ASSERT(value["test"].IsUInteger());
  219. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), (i64)(Max<i64>() + 1ull));
  220. } // Max<i64>() + 1
  221. }
  222. Y_UNIT_TEST(TJsonUnsignedIntegerTest) {
  223. {
  224. TStringStream in;
  225. in << "{ \"test\" : 1 }";
  226. TJsonValue value;
  227. UNIT_ASSERT(ReadJsonTree(&in, &value));
  228. UNIT_ASSERT(value.Has("test"));
  229. UNIT_ASSERT(value["test"].IsInteger());
  230. UNIT_ASSERT(value["test"].IsUInteger());
  231. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), 1);
  232. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), 1);
  233. UNIT_ASSERT_EQUAL(value["test"].GetUInteger(), 1);
  234. UNIT_ASSERT_EQUAL(value["test"].GetUIntegerRobust(), 1);
  235. } // 1
  236. {
  237. TStringStream in;
  238. in << "{ \"test\" : -1 }";
  239. TJsonValue value;
  240. UNIT_ASSERT(ReadJsonTree(&in, &value));
  241. UNIT_ASSERT(value.Has("test"));
  242. UNIT_ASSERT(value["test"].IsInteger());
  243. UNIT_ASSERT(!value["test"].IsUInteger());
  244. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), -1);
  245. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), -1);
  246. UNIT_ASSERT_EQUAL(value["test"].GetUInteger(), 0);
  247. UNIT_ASSERT_EQUAL(value["test"].GetUIntegerRobust(), static_cast<unsigned long long>(-1));
  248. } // -1
  249. {
  250. TStringStream in;
  251. in << "{ \"test\" : 18446744073709551615 }";
  252. TJsonValue value;
  253. UNIT_ASSERT(ReadJsonTree(&in, &value));
  254. UNIT_ASSERT(value.Has("test"));
  255. UNIT_ASSERT(!value["test"].IsInteger());
  256. UNIT_ASSERT(value["test"].IsUInteger());
  257. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), 0);
  258. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), static_cast<long long>(18446744073709551615ull));
  259. UNIT_ASSERT_EQUAL(value["test"].GetUInteger(), 18446744073709551615ull);
  260. UNIT_ASSERT_EQUAL(value["test"].GetUIntegerRobust(), 18446744073709551615ull);
  261. } // 18446744073709551615
  262. {
  263. TStringStream in;
  264. in << "{ \"test\" : 1.1 }";
  265. TJsonValue value;
  266. UNIT_ASSERT(ReadJsonTree(&in, &value));
  267. UNIT_ASSERT(value.Has("test"));
  268. UNIT_ASSERT(!value["test"].IsInteger());
  269. UNIT_ASSERT(!value["test"].IsUInteger());
  270. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), 0);
  271. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), static_cast<long long>(1.1));
  272. UNIT_ASSERT_EQUAL(value["test"].GetUInteger(), 0);
  273. UNIT_ASSERT_EQUAL(value["test"].GetUIntegerRobust(), static_cast<unsigned long long>(1.1));
  274. } // 1.1
  275. {
  276. TStringStream in;
  277. in << "{ \"test\" : [1, 18446744073709551615] }";
  278. TJsonValue value;
  279. UNIT_ASSERT(ReadJsonTree(&in, &value));
  280. UNIT_ASSERT(value.Has("test"));
  281. UNIT_ASSERT(value["test"].IsArray());
  282. UNIT_ASSERT_EQUAL(value["test"].GetArray().size(), 2);
  283. UNIT_ASSERT(value["test"][0].IsInteger());
  284. UNIT_ASSERT(value["test"][0].IsUInteger());
  285. UNIT_ASSERT_EQUAL(value["test"][0].GetInteger(), 1);
  286. UNIT_ASSERT_EQUAL(value["test"][0].GetUInteger(), 1);
  287. UNIT_ASSERT(!value["test"][1].IsInteger());
  288. UNIT_ASSERT(value["test"][1].IsUInteger());
  289. UNIT_ASSERT_EQUAL(value["test"][1].GetUInteger(), 18446744073709551615ull);
  290. }
  291. } // TJsonUnsignedIntegerTest
  292. Y_UNIT_TEST(TJsonDoubleTest) {
  293. {
  294. TStringStream in;
  295. in << "{ \"test\" : 1.0 }";
  296. TJsonValue value;
  297. UNIT_ASSERT(ReadJsonTree(&in, &value));
  298. UNIT_ASSERT(value.Has("test"));
  299. UNIT_ASSERT(value["test"].IsDouble());
  300. UNIT_ASSERT_EQUAL(value["test"].GetDouble(), 1.0);
  301. UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), 1.0);
  302. } // 1.0
  303. {
  304. TStringStream in;
  305. in << "{ \"test\" : 1 }";
  306. TJsonValue value;
  307. UNIT_ASSERT(ReadJsonTree(&in, &value));
  308. UNIT_ASSERT(value.Has("test"));
  309. UNIT_ASSERT(value["test"].IsDouble());
  310. UNIT_ASSERT_EQUAL(value["test"].GetDouble(), 1.0);
  311. UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), 1.0);
  312. } // 1
  313. {
  314. TStringStream in;
  315. in << "{ \"test\" : -1 }";
  316. TJsonValue value;
  317. UNIT_ASSERT(ReadJsonTree(&in, &value));
  318. UNIT_ASSERT(value.Has("test"));
  319. UNIT_ASSERT(value["test"].IsDouble());
  320. UNIT_ASSERT_EQUAL(value["test"].GetDouble(), -1.0);
  321. UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), -1.0);
  322. } // -1
  323. {
  324. TStringStream in;
  325. in << "{ \"test\" : " << Max<ui64>() << " }";
  326. TJsonValue value;
  327. UNIT_ASSERT(ReadJsonTree(&in, &value));
  328. UNIT_ASSERT(value.Has("test"));
  329. UNIT_ASSERT(!value["test"].IsDouble());
  330. UNIT_ASSERT_EQUAL(value["test"].GetDouble(), 0.0);
  331. UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), static_cast<double>(Max<ui64>()));
  332. } // Max<ui64>()
  333. } // TJsonDoubleTest
  334. Y_UNIT_TEST(TJsonInvalidTest) {
  335. {
  336. // No exceptions mode.
  337. TStringStream in;
  338. in << "{ \"test\" : }";
  339. TJsonValue value;
  340. UNIT_ASSERT(!ReadJsonTree(&in, &value));
  341. }
  342. {
  343. // Exception throwing mode.
  344. TStringStream in;
  345. in << "{ \"test\" : }";
  346. TJsonValue value;
  347. UNIT_ASSERT_EXCEPTION(ReadJsonTree(&in, &value, true), TJsonException);
  348. }
  349. }
  350. Y_UNIT_TEST(TJsonMemoryLeakTest) {
  351. // after https://clubs.at.yandex-team.ru/stackoverflow/3691
  352. TString s = ".";
  353. NJson::TJsonValue json;
  354. try {
  355. TStringInput in(s);
  356. NJson::ReadJsonTree(&in, &json, true);
  357. } catch (...) {
  358. }
  359. } // TJsonMemoryLeakTest
  360. Y_UNIT_TEST(TJsonDuplicateKeysWithNullValuesTest) {
  361. const TString json = "{\"\":null,\"\":\"\"}";
  362. TStringInput in(json);
  363. NJson::TJsonValue v;
  364. UNIT_ASSERT(ReadJsonTree(&in, &v));
  365. UNIT_ASSERT(v.IsMap());
  366. UNIT_ASSERT_VALUES_EQUAL(1, v.GetMap().size());
  367. UNIT_ASSERT_VALUES_EQUAL("", v.GetMap().begin()->first);
  368. UNIT_ASSERT(v.GetMap().begin()->second.IsString());
  369. UNIT_ASSERT_VALUES_EQUAL("", v.GetMap().begin()->second.GetString());
  370. }
  371. // Parsing an extremely deep json tree would result in stack overflow.
  372. // Not crashing on one is a good indicator of iterative mode.
  373. Y_UNIT_TEST(TJsonIterativeTest) {
  374. constexpr ui32 brackets = static_cast<ui32>(1e5);
  375. TStringStream jsonStream;
  376. GenerateDeepJsonArray(jsonStream, brackets);
  377. TJsonReaderConfig config;
  378. config.UseIterativeParser = true;
  379. config.MaxDepth = static_cast<ui32>(1e3);
  380. TJsonValue v;
  381. UNIT_ASSERT(!ReadJsonTree(&jsonStream, &config, &v));
  382. }
  383. Y_UNIT_TEST(TJsonMaxDepthTest) {
  384. constexpr ui32 depth = static_cast<ui32>(1e3);
  385. {
  386. TStringStream jsonStream;
  387. GenerateDeepJsonArray(jsonStream, depth);
  388. TJsonReaderConfig config;
  389. config.MaxDepth = depth;
  390. TJsonValue v;
  391. UNIT_ASSERT(ReadJsonTree(&jsonStream, &config, &v));
  392. }
  393. {
  394. TStringStream jsonStream;
  395. GenerateDeepJsonArray(jsonStream, depth);
  396. TJsonReaderConfig config;
  397. config.MaxDepth = depth - 1;
  398. TJsonValue v;
  399. UNIT_ASSERT(!ReadJsonTree(&jsonStream, &config, &v));
  400. }
  401. {
  402. TStringStream jsonStream;
  403. GenerateDeepJsonDict(jsonStream, depth);
  404. TJsonReaderConfig config;
  405. config.MaxDepth = depth;
  406. TJsonValue v;
  407. UNIT_ASSERT(ReadJsonTree(&jsonStream, &config, &v));
  408. }
  409. {
  410. TStringStream jsonStream;
  411. GenerateDeepJsonDict(jsonStream, depth);
  412. TJsonReaderConfig config;
  413. config.MaxDepth = depth - 1;
  414. TJsonValue v;
  415. UNIT_ASSERT(!ReadJsonTree(&jsonStream, &config, &v));
  416. }
  417. }
  418. }
  419. static const TString YANDEX_STREAMING_JSON("{\"a\":1}//d{\"b\":2}");
  420. Y_UNIT_TEST_SUITE(TCompareReadJsonFast) {
  421. Y_UNIT_TEST(NoEndl) {
  422. NJson::TJsonValue parsed;
  423. bool success = NJson::ReadJsonTree(YANDEX_STREAMING_JSON, &parsed, false);
  424. bool fast_success = NJson::ReadJsonFastTree(YANDEX_STREAMING_JSON, &parsed, false);
  425. UNIT_ASSERT(success == fast_success);
  426. }
  427. Y_UNIT_TEST(WithEndl) {
  428. NJson::TJsonValue parsed1;
  429. NJson::TJsonValue parsed2;
  430. bool success = NJson::ReadJsonTree(YANDEX_STREAMING_JSON + "\n", &parsed1, false);
  431. bool fast_success = NJson::ReadJsonFastTree(YANDEX_STREAMING_JSON + "\n", &parsed2, false);
  432. UNIT_ASSERT_VALUES_EQUAL(success, fast_success);
  433. }
  434. Y_UNIT_TEST(NoQuotes) {
  435. TString streamingJson = "{a:1}";
  436. NJson::TJsonValue parsed;
  437. bool success = NJson::ReadJsonTree(streamingJson, &parsed, false);
  438. bool fast_success = NJson::ReadJsonFastTree(streamingJson, &parsed, false);
  439. UNIT_ASSERT(success != fast_success);
  440. }
  441. }