json_reader_ut.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  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. Y_UNIT_TEST_SUITE(TJsonReaderTest) {
  55. Y_UNIT_TEST(JsonReformatTest) {
  56. TString data = "{\"null value\": null, \"intkey\": 10, \"double key\": 11.11, \"string key\": \"string\", \"array\": [1,2,3,\"TString\"], \"bool key\": true}";
  57. TString result1, result2;
  58. {
  59. TStringStream in;
  60. in << data;
  61. TStringStream out;
  62. TJsonWriter writer(&out, false);
  63. TReformatCallbacks cb(writer);
  64. ReadJson(&in, &cb);
  65. writer.Flush();
  66. result1 = out.Str();
  67. }
  68. {
  69. TStringStream in;
  70. in << result1;
  71. TStringStream out;
  72. TJsonWriter writer(&out, false);
  73. TReformatCallbacks cb(writer);
  74. ReadJson(&in, &cb);
  75. writer.Flush();
  76. result2 = out.Str();
  77. }
  78. UNIT_ASSERT_VALUES_EQUAL(result1, result2);
  79. }
  80. Y_UNIT_TEST(TJsonEscapedApostrophe) {
  81. TString jsonString = "{ \"foo\" : \"bar\\'buzz\" }";
  82. {
  83. TStringStream in;
  84. in << jsonString;
  85. TStringStream out;
  86. TJsonWriter writer(&out, false);
  87. TReformatCallbacks cb(writer);
  88. UNIT_ASSERT(!ReadJson(&in, &cb));
  89. }
  90. {
  91. TStringStream in;
  92. in << jsonString;
  93. TStringStream out;
  94. TJsonWriter writer(&out, false);
  95. TReformatCallbacks cb(writer);
  96. UNIT_ASSERT(ReadJson(&in, false, true, &cb));
  97. writer.Flush();
  98. UNIT_ASSERT_EQUAL(out.Str(), "[\"foo\",\"bar'buzz\"]");
  99. }
  100. }
  101. Y_UNIT_TEST(TJsonTreeTest) {
  102. TString data = "{\"intkey\": 10, \"double key\": 11.11, \"null value\":null, \"string key\": \"string\", \"array\": [1,2,3,\"TString\"], \"bool key\": true}";
  103. TStringStream in;
  104. in << data;
  105. TJsonValue value;
  106. ReadJsonTree(&in, &value);
  107. UNIT_ASSERT_VALUES_EQUAL(value["intkey"].GetInteger(), 10);
  108. UNIT_ASSERT_DOUBLES_EQUAL(value["double key"].GetDouble(), 11.11, 0.001);
  109. UNIT_ASSERT_VALUES_EQUAL(value["bool key"].GetBoolean(), true);
  110. UNIT_ASSERT_VALUES_EQUAL(value["absent string key"].GetString(), TString(""));
  111. UNIT_ASSERT_VALUES_EQUAL(value["string key"].GetString(), TString("string"));
  112. UNIT_ASSERT_VALUES_EQUAL(value["array"][0].GetInteger(), 1);
  113. UNIT_ASSERT_VALUES_EQUAL(value["array"][1].GetInteger(), 2);
  114. UNIT_ASSERT_VALUES_EQUAL(value["array"][2].GetInteger(), 3);
  115. UNIT_ASSERT_VALUES_EQUAL(value["array"][3].GetString(), TString("TString"));
  116. UNIT_ASSERT(value["null value"].IsNull());
  117. // AsString
  118. UNIT_ASSERT_VALUES_EQUAL(value["intkey"].GetStringRobust(), "10");
  119. UNIT_ASSERT_VALUES_EQUAL(value["double key"].GetStringRobust(), "11.11");
  120. UNIT_ASSERT_VALUES_EQUAL(value["bool key"].GetStringRobust(), "true");
  121. UNIT_ASSERT_VALUES_EQUAL(value["string key"].GetStringRobust(), "string");
  122. UNIT_ASSERT_VALUES_EQUAL(value["array"].GetStringRobust(), "[1,2,3,\"TString\"]");
  123. UNIT_ASSERT_VALUES_EQUAL(value["null value"].GetStringRobust(), "null");
  124. const TJsonValue::TArray* array;
  125. UNIT_ASSERT(GetArrayPointer(value, "array", &array));
  126. UNIT_ASSERT_VALUES_EQUAL(value["array"].GetArray().size(), array->size());
  127. UNIT_ASSERT_VALUES_EQUAL(value["array"][0].GetInteger(), (*array)[0].GetInteger());
  128. UNIT_ASSERT_VALUES_EQUAL(value["array"][1].GetInteger(), (*array)[1].GetInteger());
  129. UNIT_ASSERT_VALUES_EQUAL(value["array"][2].GetInteger(), (*array)[2].GetInteger());
  130. UNIT_ASSERT_VALUES_EQUAL(value["array"][3].GetString(), (*array)[3].GetString());
  131. }
  132. Y_UNIT_TEST(TJsonRomaTest) {
  133. TString data = "{\"test\": [ {\"name\": \"A\"} ]}";
  134. TStringStream in;
  135. in << data;
  136. TJsonValue value;
  137. ReadJsonTree(&in, &value);
  138. UNIT_ASSERT_VALUES_EQUAL(value["test"][0]["name"].GetString(), TString("A"));
  139. }
  140. Y_UNIT_TEST(TJsonReadTreeWithComments) {
  141. {
  142. TString leadingCommentData = "{ // \"test\" : 1 \n}";
  143. {
  144. // No comments allowed
  145. TStringStream in;
  146. in << leadingCommentData;
  147. TJsonValue value;
  148. UNIT_ASSERT(!ReadJsonTree(&in, false, &value));
  149. }
  150. {
  151. // Comments allowed
  152. TStringStream in;
  153. in << leadingCommentData;
  154. TJsonValue value;
  155. UNIT_ASSERT(ReadJsonTree(&in, true, &value));
  156. UNIT_ASSERT(!value.Has("test"));
  157. }
  158. }
  159. {
  160. TString trailingCommentData = "{ \"test1\" : 1 // \"test2\" : 2 \n }";
  161. {
  162. // No comments allowed
  163. TStringStream in;
  164. in << trailingCommentData;
  165. TJsonValue value;
  166. UNIT_ASSERT(!ReadJsonTree(&in, false, &value));
  167. }
  168. {
  169. // Comments allowed
  170. TStringStream in;
  171. in << trailingCommentData;
  172. TJsonValue value;
  173. UNIT_ASSERT(ReadJsonTree(&in, true, &value));
  174. UNIT_ASSERT(value.Has("test1"));
  175. UNIT_ASSERT_EQUAL(value["test1"].GetInteger(), 1);
  176. UNIT_ASSERT(!value.Has("test2"));
  177. }
  178. }
  179. }
  180. Y_UNIT_TEST(TJsonSignedIntegerTest) {
  181. {
  182. TStringStream in;
  183. in << "{ \"test\" : " << Min<i64>() << " }";
  184. TJsonValue value;
  185. UNIT_ASSERT(ReadJsonTree(&in, &value));
  186. UNIT_ASSERT(value.Has("test"));
  187. UNIT_ASSERT(value["test"].IsInteger());
  188. UNIT_ASSERT(!value["test"].IsUInteger());
  189. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), Min<i64>());
  190. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), Min<i64>());
  191. } // Min<i64>()
  192. {
  193. TStringStream in;
  194. in << "{ \"test\" : " << Max<i64>() + 1ull << " }";
  195. TJsonValue value;
  196. UNIT_ASSERT(ReadJsonTree(&in, &value));
  197. UNIT_ASSERT(value.Has("test"));
  198. UNIT_ASSERT(!value["test"].IsInteger());
  199. UNIT_ASSERT(value["test"].IsUInteger());
  200. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), (i64)(Max<i64>() + 1ull));
  201. } // Max<i64>() + 1
  202. }
  203. Y_UNIT_TEST(TJsonUnsignedIntegerTest) {
  204. {
  205. TStringStream in;
  206. in << "{ \"test\" : 1 }";
  207. TJsonValue value;
  208. UNIT_ASSERT(ReadJsonTree(&in, &value));
  209. UNIT_ASSERT(value.Has("test"));
  210. UNIT_ASSERT(value["test"].IsInteger());
  211. UNIT_ASSERT(value["test"].IsUInteger());
  212. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), 1);
  213. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), 1);
  214. UNIT_ASSERT_EQUAL(value["test"].GetUInteger(), 1);
  215. UNIT_ASSERT_EQUAL(value["test"].GetUIntegerRobust(), 1);
  216. } // 1
  217. {
  218. TStringStream in;
  219. in << "{ \"test\" : -1 }";
  220. TJsonValue value;
  221. UNIT_ASSERT(ReadJsonTree(&in, &value));
  222. UNIT_ASSERT(value.Has("test"));
  223. UNIT_ASSERT(value["test"].IsInteger());
  224. UNIT_ASSERT(!value["test"].IsUInteger());
  225. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), -1);
  226. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), -1);
  227. UNIT_ASSERT_EQUAL(value["test"].GetUInteger(), 0);
  228. UNIT_ASSERT_EQUAL(value["test"].GetUIntegerRobust(), static_cast<unsigned long long>(-1));
  229. } // -1
  230. {
  231. TStringStream in;
  232. in << "{ \"test\" : 18446744073709551615 }";
  233. TJsonValue value;
  234. UNIT_ASSERT(ReadJsonTree(&in, &value));
  235. UNIT_ASSERT(value.Has("test"));
  236. UNIT_ASSERT(!value["test"].IsInteger());
  237. UNIT_ASSERT(value["test"].IsUInteger());
  238. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), 0);
  239. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), static_cast<long long>(18446744073709551615ull));
  240. UNIT_ASSERT_EQUAL(value["test"].GetUInteger(), 18446744073709551615ull);
  241. UNIT_ASSERT_EQUAL(value["test"].GetUIntegerRobust(), 18446744073709551615ull);
  242. } // 18446744073709551615
  243. {
  244. TStringStream in;
  245. in << "{ \"test\" : 1.1 }";
  246. TJsonValue value;
  247. UNIT_ASSERT(ReadJsonTree(&in, &value));
  248. UNIT_ASSERT(value.Has("test"));
  249. UNIT_ASSERT(!value["test"].IsInteger());
  250. UNIT_ASSERT(!value["test"].IsUInteger());
  251. UNIT_ASSERT_EQUAL(value["test"].GetInteger(), 0);
  252. UNIT_ASSERT_EQUAL(value["test"].GetIntegerRobust(), static_cast<long long>(1.1));
  253. UNIT_ASSERT_EQUAL(value["test"].GetUInteger(), 0);
  254. UNIT_ASSERT_EQUAL(value["test"].GetUIntegerRobust(), static_cast<unsigned long long>(1.1));
  255. } // 1.1
  256. {
  257. TStringStream in;
  258. in << "{ \"test\" : [1, 18446744073709551615] }";
  259. TJsonValue value;
  260. UNIT_ASSERT(ReadJsonTree(&in, &value));
  261. UNIT_ASSERT(value.Has("test"));
  262. UNIT_ASSERT(value["test"].IsArray());
  263. UNIT_ASSERT_EQUAL(value["test"].GetArray().size(), 2);
  264. UNIT_ASSERT(value["test"][0].IsInteger());
  265. UNIT_ASSERT(value["test"][0].IsUInteger());
  266. UNIT_ASSERT_EQUAL(value["test"][0].GetInteger(), 1);
  267. UNIT_ASSERT_EQUAL(value["test"][0].GetUInteger(), 1);
  268. UNIT_ASSERT(!value["test"][1].IsInteger());
  269. UNIT_ASSERT(value["test"][1].IsUInteger());
  270. UNIT_ASSERT_EQUAL(value["test"][1].GetUInteger(), 18446744073709551615ull);
  271. }
  272. } // TJsonUnsignedIntegerTest
  273. Y_UNIT_TEST(TJsonDoubleTest) {
  274. {
  275. TStringStream in;
  276. in << "{ \"test\" : 1.0 }";
  277. TJsonValue value;
  278. UNIT_ASSERT(ReadJsonTree(&in, &value));
  279. UNIT_ASSERT(value.Has("test"));
  280. UNIT_ASSERT(value["test"].IsDouble());
  281. UNIT_ASSERT_EQUAL(value["test"].GetDouble(), 1.0);
  282. UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), 1.0);
  283. } // 1.0
  284. {
  285. TStringStream in;
  286. in << "{ \"test\" : 1 }";
  287. TJsonValue value;
  288. UNIT_ASSERT(ReadJsonTree(&in, &value));
  289. UNIT_ASSERT(value.Has("test"));
  290. UNIT_ASSERT(value["test"].IsDouble());
  291. UNIT_ASSERT_EQUAL(value["test"].GetDouble(), 1.0);
  292. UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), 1.0);
  293. } // 1
  294. {
  295. TStringStream in;
  296. in << "{ \"test\" : -1 }";
  297. TJsonValue value;
  298. UNIT_ASSERT(ReadJsonTree(&in, &value));
  299. UNIT_ASSERT(value.Has("test"));
  300. UNIT_ASSERT(value["test"].IsDouble());
  301. UNIT_ASSERT_EQUAL(value["test"].GetDouble(), -1.0);
  302. UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), -1.0);
  303. } // -1
  304. {
  305. TStringStream in;
  306. in << "{ \"test\" : " << Max<ui64>() << " }";
  307. TJsonValue value;
  308. UNIT_ASSERT(ReadJsonTree(&in, &value));
  309. UNIT_ASSERT(value.Has("test"));
  310. UNIT_ASSERT(!value["test"].IsDouble());
  311. UNIT_ASSERT_EQUAL(value["test"].GetDouble(), 0.0);
  312. UNIT_ASSERT_EQUAL(value["test"].GetDoubleRobust(), static_cast<double>(Max<ui64>()));
  313. } // Max<ui64>()
  314. } // TJsonDoubleTest
  315. Y_UNIT_TEST(TJsonInvalidTest) {
  316. {
  317. // No exceptions mode.
  318. TStringStream in;
  319. in << "{ \"test\" : }";
  320. TJsonValue value;
  321. UNIT_ASSERT(!ReadJsonTree(&in, &value));
  322. }
  323. {
  324. // Exception throwing mode.
  325. TStringStream in;
  326. in << "{ \"test\" : }";
  327. TJsonValue value;
  328. UNIT_ASSERT_EXCEPTION(ReadJsonTree(&in, &value, true), TJsonException);
  329. }
  330. }
  331. Y_UNIT_TEST(TJsonMemoryLeakTest) {
  332. // after https://clubs.at.yandex-team.ru/stackoverflow/3691
  333. TString s = ".";
  334. NJson::TJsonValue json;
  335. try {
  336. TStringInput in(s);
  337. NJson::ReadJsonTree(&in, &json, true);
  338. } catch (...) {
  339. }
  340. } // TJsonMemoryLeakTest
  341. Y_UNIT_TEST(TJsonDuplicateKeysWithNullValuesTest) {
  342. const TString json = "{\"\":null,\"\":\"\"}";
  343. TStringInput in(json);
  344. NJson::TJsonValue v;
  345. UNIT_ASSERT(ReadJsonTree(&in, &v));
  346. UNIT_ASSERT(v.IsMap());
  347. UNIT_ASSERT_VALUES_EQUAL(1, v.GetMap().size());
  348. UNIT_ASSERT_VALUES_EQUAL("", v.GetMap().begin()->first);
  349. UNIT_ASSERT(v.GetMap().begin()->second.IsString());
  350. UNIT_ASSERT_VALUES_EQUAL("", v.GetMap().begin()->second.GetString());
  351. }
  352. }
  353. static const TString YANDEX_STREAMING_JSON("{\"a\":1}//d{\"b\":2}");
  354. Y_UNIT_TEST_SUITE(TCompareReadJsonFast) {
  355. Y_UNIT_TEST(NoEndl) {
  356. NJson::TJsonValue parsed;
  357. bool success = NJson::ReadJsonTree(YANDEX_STREAMING_JSON, &parsed, false);
  358. bool fast_success = NJson::ReadJsonFastTree(YANDEX_STREAMING_JSON, &parsed, false);
  359. UNIT_ASSERT(success == fast_success);
  360. }
  361. Y_UNIT_TEST(WithEndl) {
  362. NJson::TJsonValue parsed1;
  363. NJson::TJsonValue parsed2;
  364. bool success = NJson::ReadJsonTree(YANDEX_STREAMING_JSON + "\n", &parsed1, false);
  365. bool fast_success = NJson::ReadJsonFastTree(YANDEX_STREAMING_JSON + "\n", &parsed2, false);
  366. UNIT_ASSERT_VALUES_EQUAL(success, fast_success);
  367. }
  368. Y_UNIT_TEST(NoQuotes) {
  369. TString streamingJson = "{a:1}";
  370. NJson::TJsonValue parsed;
  371. bool success = NJson::ReadJsonTree(streamingJson, &parsed, false);
  372. bool fast_success = NJson::ReadJsonFastTree(streamingJson, &parsed, false);
  373. UNIT_ASSERT(success != fast_success);
  374. }
  375. }