JsonTest.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /*
  2. * Copyright 2011-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/json.h>
  17. #include <iterator>
  18. #include <limits>
  19. #include <folly/portability/GTest.h>
  20. using folly::dynamic;
  21. using folly::parseJson;
  22. using folly::toJson;
  23. TEST(Json, Unicode) {
  24. auto val = parseJson(u8"\"I \u2665 UTF-8\"");
  25. EXPECT_EQ(u8"I \u2665 UTF-8", val.asString());
  26. val = parseJson("\"I \\u2665 UTF-8\"");
  27. EXPECT_EQ(u8"I \u2665 UTF-8", val.asString());
  28. val = parseJson(u8"\"I \U0001D11E playing in G-clef\"");
  29. EXPECT_EQ(u8"I \U0001D11E playing in G-clef", val.asString());
  30. val = parseJson("\"I \\uD834\\uDD1E playing in G-clef\"");
  31. EXPECT_EQ(u8"I \U0001D11E playing in G-clef", val.asString());
  32. }
  33. TEST(Json, Parse) {
  34. auto num = parseJson("12");
  35. EXPECT_TRUE(num.isInt());
  36. EXPECT_EQ(num, 12);
  37. num = parseJson("12e5");
  38. EXPECT_TRUE(num.isDouble());
  39. EXPECT_EQ(num, 12e5);
  40. auto numAs1 = num.asDouble();
  41. EXPECT_EQ(numAs1, 12e5);
  42. EXPECT_EQ(num, 12e5);
  43. EXPECT_EQ(num, 1200000);
  44. auto largeNumber = parseJson("4611686018427387904");
  45. EXPECT_TRUE(largeNumber.isInt());
  46. EXPECT_EQ(largeNumber, 4611686018427387904L);
  47. auto negative = parseJson("-123");
  48. EXPECT_EQ(negative, -123);
  49. auto bfalse = parseJson("false");
  50. auto btrue = parseJson("true");
  51. EXPECT_EQ(bfalse, false);
  52. EXPECT_EQ(btrue, true);
  53. auto null = parseJson("null");
  54. EXPECT_TRUE(null == nullptr);
  55. auto doub1 = parseJson("12.0");
  56. auto doub2 = parseJson("12e2");
  57. EXPECT_EQ(doub1, 12.0);
  58. EXPECT_EQ(doub2, 12e2);
  59. EXPECT_EQ(
  60. std::numeric_limits<double>::infinity(),
  61. parseJson("Infinity").asDouble());
  62. EXPECT_EQ(
  63. -std::numeric_limits<double>::infinity(),
  64. parseJson("-Infinity").asDouble());
  65. EXPECT_TRUE(std::isnan(parseJson("NaN").asDouble()));
  66. // case matters
  67. EXPECT_THROW(parseJson("infinity"), std::runtime_error);
  68. EXPECT_THROW(parseJson("inf"), std::runtime_error);
  69. EXPECT_THROW(parseJson("Inf"), std::runtime_error);
  70. EXPECT_THROW(parseJson("INF"), std::runtime_error);
  71. EXPECT_THROW(parseJson("nan"), std::runtime_error);
  72. EXPECT_THROW(parseJson("NAN"), std::runtime_error);
  73. auto array = parseJson("[12,false, false , null , [12e4,32, [], 12]]");
  74. EXPECT_EQ(array.size(), 5);
  75. if (array.size() == 5) {
  76. EXPECT_EQ(std::prev(array.end())->size(), 4);
  77. }
  78. EXPECT_THROW(parseJson("\n[12,\n\nnotvalidjson"), std::runtime_error);
  79. EXPECT_THROW(parseJson("12e2e2"), std::runtime_error);
  80. EXPECT_THROW(
  81. parseJson("{\"foo\":12,\"bar\":42} \"something\""), std::runtime_error);
  82. // clang-format off
  83. dynamic value = dynamic::object
  84. ("foo", "bar")
  85. ("junk", 12)
  86. ("another", 32.2)
  87. ("a",
  88. dynamic::array(
  89. dynamic::object("a", "b")("c", "d"),
  90. 12.5,
  91. "Yo Dawg",
  92. dynamic::array("heh"),
  93. nullptr));
  94. // clang-format on
  95. // Print then parse and get the same thing, hopefully.
  96. EXPECT_EQ(value, parseJson(toJson(value)));
  97. // Test an object with non-string values.
  98. dynamic something =
  99. parseJson("{\"old_value\":40,\"changed\":true,\"opened\":false}");
  100. dynamic expected =
  101. dynamic::object("old_value", 40)("changed", true)("opened", false);
  102. EXPECT_EQ(something, expected);
  103. }
  104. TEST(Json, ParseTrailingComma) {
  105. folly::json::serialization_opts on, off;
  106. on.allow_trailing_comma = true;
  107. off.allow_trailing_comma = false;
  108. dynamic arr = dynamic::array(1, 2);
  109. EXPECT_EQ(arr, parseJson("[1, 2]", on));
  110. EXPECT_EQ(arr, parseJson("[1, 2,]", on));
  111. EXPECT_EQ(arr, parseJson("[1, 2, ]", on));
  112. EXPECT_EQ(arr, parseJson("[1, 2 , ]", on));
  113. EXPECT_EQ(arr, parseJson("[1, 2 ,]", on));
  114. EXPECT_THROW(parseJson("[1, 2,]", off), std::runtime_error);
  115. dynamic obj = dynamic::object("a", 1);
  116. EXPECT_EQ(obj, parseJson("{\"a\": 1}", on));
  117. EXPECT_EQ(obj, parseJson("{\"a\": 1,}", on));
  118. EXPECT_EQ(obj, parseJson("{\"a\": 1, }", on));
  119. EXPECT_EQ(obj, parseJson("{\"a\": 1 , }", on));
  120. EXPECT_EQ(obj, parseJson("{\"a\": 1 ,}", on));
  121. EXPECT_THROW(parseJson("{\"a\":1,}", off), std::runtime_error);
  122. }
  123. TEST(Json, BoolConversion) {
  124. EXPECT_TRUE(parseJson("42").asBool());
  125. }
  126. TEST(Json, JavascriptSafe) {
  127. auto badDouble = int64_t((1ULL << 63ULL) + 1);
  128. dynamic badDyn = badDouble;
  129. EXPECT_EQ(folly::toJson(badDouble), folly::to<std::string>(badDouble));
  130. folly::json::serialization_opts opts;
  131. opts.javascript_safe = true;
  132. EXPECT_ANY_THROW(folly::json::serialize(badDouble, opts));
  133. auto okDouble = int64_t(1ULL << 63ULL);
  134. dynamic okDyn = okDouble;
  135. EXPECT_EQ(folly::toJson(okDouble), folly::to<std::string>(okDouble));
  136. }
  137. TEST(Json, Produce) {
  138. auto value = parseJson(R"( "f\"oo" )");
  139. EXPECT_EQ(toJson(value), R"("f\"oo")");
  140. value = parseJson("\"Control code: \001 \002 \x1f\"");
  141. EXPECT_EQ(toJson(value), R"("Control code: \u0001 \u0002 \u001f")");
  142. // We're not allowed to have non-string keys in json.
  143. EXPECT_THROW(
  144. toJson(dynamic::object("abc", "xyz")(42.33, "asd")), std::runtime_error);
  145. // Check Infinity/Nan
  146. folly::json::serialization_opts opts;
  147. opts.allow_nan_inf = true;
  148. EXPECT_EQ("Infinity", folly::json::serialize(parseJson("Infinity"), opts));
  149. EXPECT_EQ("NaN", folly::json::serialize(parseJson("NaN"), opts));
  150. }
  151. TEST(Json, JsonEscape) {
  152. folly::json::serialization_opts opts;
  153. EXPECT_EQ(
  154. folly::json::serialize("\b\f\n\r\x01\t\\\"/\v\a", opts),
  155. R"("\b\f\n\r\u0001\t\\\"/\u000b\u0007")");
  156. }
  157. TEST(Json, EscapeCornerCases) {
  158. // The escaping logic uses some bitwise operations to determine
  159. // which bytes need escaping 8 bytes at a time. Test that this logic
  160. // is correct regardless of positions by planting 2 characters that
  161. // may need escaping at each possible position and checking the
  162. // result, for varying string lengths.
  163. folly::json::serialization_opts opts;
  164. opts.validate_utf8 = true;
  165. std::string s;
  166. std::string expected;
  167. for (bool ascii : {true, false}) {
  168. opts.encode_non_ascii = ascii;
  169. for (size_t len = 2; len < 32; ++len) {
  170. for (size_t i = 0; i < len; ++i) {
  171. for (size_t j = 0; j < len; ++j) {
  172. if (i == j) {
  173. continue;
  174. }
  175. s.clear();
  176. expected.clear();
  177. expected.push_back('"');
  178. for (size_t pos = 0; pos < len; ++pos) {
  179. if (pos == i) {
  180. s.push_back('\\');
  181. expected.append("\\\\");
  182. } else if (pos == j) {
  183. s.append("\xe2\x82\xac");
  184. expected.append(ascii ? "\\u20ac" : "\xe2\x82\xac");
  185. } else {
  186. s.push_back('x');
  187. expected.push_back('x');
  188. }
  189. }
  190. expected.push_back('"');
  191. EXPECT_EQ(folly::json::serialize(s, opts), expected) << ascii;
  192. }
  193. }
  194. }
  195. }
  196. }
  197. TEST(Json, JsonNonAsciiEncoding) {
  198. folly::json::serialization_opts opts;
  199. opts.encode_non_ascii = true;
  200. // simple tests
  201. EXPECT_EQ(folly::json::serialize("\x1f", opts), R"("\u001f")");
  202. EXPECT_EQ(folly::json::serialize("\xc2\xa2", opts), R"("\u00a2")");
  203. EXPECT_EQ(folly::json::serialize("\xe2\x82\xac", opts), R"("\u20ac")");
  204. // multiple unicode encodings
  205. EXPECT_EQ(
  206. folly::json::serialize("\x1f\xe2\x82\xac", opts), R"("\u001f\u20ac")");
  207. EXPECT_EQ(
  208. folly::json::serialize("\x1f\xc2\xa2\xe2\x82\xac", opts),
  209. R"("\u001f\u00a2\u20ac")");
  210. EXPECT_EQ(
  211. folly::json::serialize("\xc2\x80\xef\xbf\xbf", opts),
  212. R"("\u0080\uffff")");
  213. EXPECT_EQ(
  214. folly::json::serialize("\xe0\xa0\x80\xdf\xbf", opts),
  215. R"("\u0800\u07ff")");
  216. // first possible sequence of a certain length
  217. EXPECT_EQ(folly::json::serialize("\xc2\x80", opts), R"("\u0080")");
  218. EXPECT_EQ(folly::json::serialize("\xe0\xa0\x80", opts), R"("\u0800")");
  219. // last possible sequence of a certain length
  220. EXPECT_EQ(folly::json::serialize("\xdf\xbf", opts), R"("\u07ff")");
  221. EXPECT_EQ(folly::json::serialize("\xef\xbf\xbf", opts), R"("\uffff")");
  222. // other boundary conditions
  223. EXPECT_EQ(folly::json::serialize("\xed\x9f\xbf", opts), R"("\ud7ff")");
  224. EXPECT_EQ(folly::json::serialize("\xee\x80\x80", opts), R"("\ue000")");
  225. EXPECT_EQ(folly::json::serialize("\xef\xbf\xbd", opts), R"("\ufffd")");
  226. // incomplete sequences
  227. EXPECT_ANY_THROW(folly::json::serialize("a\xed\x9f", opts));
  228. EXPECT_ANY_THROW(folly::json::serialize("b\xee\x80", opts));
  229. EXPECT_ANY_THROW(folly::json::serialize("c\xef\xbf", opts));
  230. // impossible bytes
  231. EXPECT_ANY_THROW(folly::json::serialize("\xfe", opts));
  232. EXPECT_ANY_THROW(folly::json::serialize("\xff", opts));
  233. // Sample overlong sequences
  234. EXPECT_ANY_THROW(folly::json::serialize("\xc0\xaf", opts));
  235. EXPECT_ANY_THROW(folly::json::serialize("\xe0\x80\xaf", opts));
  236. // Maximum overlong sequences
  237. EXPECT_ANY_THROW(folly::json::serialize("\xc1\xbf", opts));
  238. EXPECT_ANY_THROW(folly::json::serialize("\x30\x9f\xbf", opts));
  239. // illegal code positions
  240. EXPECT_ANY_THROW(folly::json::serialize("\xed\xa0\x80", opts));
  241. EXPECT_ANY_THROW(folly::json::serialize("\xed\xbf\xbf", opts));
  242. // Overlong representation of NUL character
  243. EXPECT_ANY_THROW(folly::json::serialize("\xc0\x80", opts));
  244. EXPECT_ANY_THROW(folly::json::serialize("\xe0\x80\x80", opts));
  245. // Allow 4 byte encodings, escape using 2 UTF-16 surrogate pairs.
  246. // "\xf0\x9f\x8d\x80" is Unicode Character 'FOUR LEAF CLOVER' (U+1F340)
  247. // >>> json.dumps({"a": u"\U0001F340"})
  248. // '{"a": "\\ud83c\\udf40"}'
  249. EXPECT_EQ(
  250. folly::json::serialize("\xf0\x9f\x8d\x80", opts), R"("\ud83c\udf40")");
  251. // Longer than 4 byte encodings
  252. EXPECT_ANY_THROW(folly::json::serialize("\xed\xaf\xbf\xed\xbf\xbf", opts));
  253. }
  254. TEST(Json, UTF8Retention) {
  255. // test retention with valid utf8 strings
  256. std::string input = u8"\u2665";
  257. std::string jsonInput = folly::toJson(input);
  258. std::string output = folly::parseJson(jsonInput).asString();
  259. std::string jsonOutput = folly::toJson(output);
  260. EXPECT_EQ(input, output);
  261. EXPECT_EQ(jsonInput, jsonOutput);
  262. // test retention with invalid utf8 - note that non-ascii chars are retained
  263. // as is, and no unicode encoding is attempted so no exception is thrown.
  264. EXPECT_EQ(
  265. folly::toJson("a\xe0\xa0\x80z\xc0\x80"), "\"a\xe0\xa0\x80z\xc0\x80\"");
  266. }
  267. TEST(Json, UTF8EncodeNonAsciiRetention) {
  268. folly::json::serialization_opts opts;
  269. opts.encode_non_ascii = true;
  270. // test encode_non_ascii valid utf8 strings
  271. std::string input = u8"\u2665";
  272. std::string jsonInput = folly::json::serialize(input, opts);
  273. std::string output = folly::parseJson(jsonInput).asString();
  274. std::string jsonOutput = folly::json::serialize(output, opts);
  275. EXPECT_EQ(input, output);
  276. EXPECT_EQ(jsonInput, jsonOutput);
  277. // test encode_non_ascii with invalid utf8 - note that an attempt to encode
  278. // non-ascii to unicode will result is a utf8 validation and throw exceptions.
  279. EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts));
  280. EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xe0\x80\x80", opts));
  281. }
  282. TEST(Json, UTF8Validation) {
  283. folly::json::serialization_opts opts;
  284. opts.validate_utf8 = true;
  285. // test validate_utf8 valid utf8 strings - note that we only validate the
  286. // for utf8 but don't encode non-ascii to unicode so they are retained as is.
  287. EXPECT_EQ(folly::json::serialize("a\xc2\x80z", opts), "\"a\xc2\x80z\"");
  288. EXPECT_EQ(
  289. folly::json::serialize("a\xe0\xa0\x80z", opts), "\"a\xe0\xa0\x80z\"");
  290. EXPECT_EQ(
  291. folly::json::serialize("a\xe0\xa0\x80m\xc2\x80z", opts),
  292. "\"a\xe0\xa0\x80m\xc2\x80z\"");
  293. // test validate_utf8 with invalid utf8
  294. EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts));
  295. EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xe0\x80\x80", opts));
  296. opts.skip_invalid_utf8 = true;
  297. EXPECT_EQ(
  298. folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts),
  299. u8"\"a\xe0\xa0\x80z\ufffd\ufffd\"");
  300. EXPECT_EQ(
  301. folly::json::serialize("a\xe0\xa0\x80z\xc0\x80\x80", opts),
  302. u8"\"a\xe0\xa0\x80z\ufffd\ufffd\ufffd\"");
  303. EXPECT_EQ(
  304. folly::json::serialize("z\xc0\x80z\xe0\xa0\x80", opts),
  305. u8"\"z\ufffd\ufffdz\xe0\xa0\x80\"");
  306. opts.encode_non_ascii = true;
  307. EXPECT_EQ(
  308. folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts),
  309. "\"a\\u0800z\\ufffd\\ufffd\"");
  310. EXPECT_EQ(
  311. folly::json::serialize("a\xe0\xa0\x80z\xc0\x80\x80", opts),
  312. "\"a\\u0800z\\ufffd\\ufffd\\ufffd\"");
  313. EXPECT_EQ(
  314. folly::json::serialize("z\xc0\x80z\xe0\xa0\x80", opts),
  315. "\"z\\ufffd\\ufffdz\\u0800\"");
  316. }
  317. TEST(Json, ParseNonStringKeys) {
  318. // test string keys
  319. EXPECT_EQ("a", parseJson("{\"a\":[]}").items().begin()->first.asString());
  320. // check that we don't allow non-string keys as this violates the
  321. // strict JSON spec (though it is emitted by the output of
  322. // folly::dynamic with operator <<).
  323. EXPECT_THROW(parseJson("{1:[]}"), std::runtime_error);
  324. // check that we can parse colloquial JSON if the option is set
  325. folly::json::serialization_opts opts;
  326. opts.allow_non_string_keys = true;
  327. auto val = parseJson("{1:[]}", opts);
  328. EXPECT_EQ(1, val.items().begin()->first.asInt());
  329. // test we can still read in strings
  330. auto sval = parseJson("{\"a\":[]}", opts);
  331. EXPECT_EQ("a", sval.items().begin()->first.asString());
  332. // test we can read in doubles
  333. auto dval = parseJson("{1.5:[]}", opts);
  334. EXPECT_EQ(1.5, dval.items().begin()->first.asDouble());
  335. }
  336. TEST(Json, ParseDoubleFallback) {
  337. // default behavior
  338. EXPECT_THROW(
  339. parseJson("{\"a\":847605071342477600000000000000}"), std::range_error);
  340. EXPECT_THROW(parseJson("{\"a\":-9223372036854775809}"), std::range_error);
  341. EXPECT_THROW(parseJson("{\"a\":9223372036854775808}"), std::range_error);
  342. EXPECT_EQ(
  343. std::numeric_limits<int64_t>::min(),
  344. parseJson("{\"a\":-9223372036854775808}")
  345. .items()
  346. .begin()
  347. ->second.asInt());
  348. EXPECT_EQ(
  349. std::numeric_limits<int64_t>::max(),
  350. parseJson("{\"a\":9223372036854775807}").items().begin()->second.asInt());
  351. // with double_fallback
  352. folly::json::serialization_opts opts;
  353. opts.double_fallback = true;
  354. EXPECT_EQ(
  355. 847605071342477600000000000000.0,
  356. parseJson("{\"a\":847605071342477600000000000000}", opts)
  357. .items()
  358. .begin()
  359. ->second.asDouble());
  360. EXPECT_EQ(
  361. 847605071342477600000000000000.0,
  362. parseJson("{\"a\": 847605071342477600000000000000}", opts)
  363. .items()
  364. .begin()
  365. ->second.asDouble());
  366. EXPECT_EQ(
  367. 847605071342477600000000000000.0,
  368. parseJson("{\"a\":847605071342477600000000000000 }", opts)
  369. .items()
  370. .begin()
  371. ->second.asDouble());
  372. EXPECT_EQ(
  373. 847605071342477600000000000000.0,
  374. parseJson("{\"a\": 847605071342477600000000000000 }", opts)
  375. .items()
  376. .begin()
  377. ->second.asDouble());
  378. EXPECT_EQ(
  379. std::numeric_limits<int64_t>::min(),
  380. parseJson("{\"a\":-9223372036854775808}", opts)
  381. .items()
  382. .begin()
  383. ->second.asInt());
  384. EXPECT_EQ(
  385. std::numeric_limits<int64_t>::max(),
  386. parseJson("{\"a\":9223372036854775807}", opts)
  387. .items()
  388. .begin()
  389. ->second.asInt());
  390. // show that some precision gets lost
  391. EXPECT_EQ(
  392. 847605071342477612345678900000.0,
  393. parseJson("{\"a\":847605071342477612345678912345}", opts)
  394. .items()
  395. .begin()
  396. ->second.asDouble());
  397. EXPECT_EQ(
  398. toJson(parseJson(R"({"a":-9223372036854775808})", opts)),
  399. R"({"a":-9223372036854775808})");
  400. }
  401. TEST(Json, ParseNumbersAsStrings) {
  402. folly::json::serialization_opts opts;
  403. opts.parse_numbers_as_strings = true;
  404. auto parse = [&](std::string number) {
  405. return parseJson(number, opts).asString();
  406. };
  407. EXPECT_EQ("0", parse("0"));
  408. EXPECT_EQ("1234", parse("1234"));
  409. EXPECT_EQ("3.00", parse("3.00"));
  410. EXPECT_EQ("3.14", parse("3.14"));
  411. EXPECT_EQ("0.1234", parse("0.1234"));
  412. EXPECT_EQ("0.0", parse("0.0"));
  413. EXPECT_EQ(
  414. "46845131213548676854213265486468451312135486768542132",
  415. parse("46845131213548676854213265486468451312135486768542132"));
  416. EXPECT_EQ(
  417. "-468451312135486768542132654864684513121354867685.5e4",
  418. parse("-468451312135486768542132654864684513121354867685.5e4"));
  419. EXPECT_EQ("6.62607004e-34", parse("6.62607004e-34"));
  420. EXPECT_EQ("6.62607004E+34", parse("6.62607004E+34"));
  421. EXPECT_EQ("Infinity", parse("Infinity"));
  422. EXPECT_EQ("-Infinity", parse("-Infinity"));
  423. EXPECT_EQ("NaN", parse("NaN"));
  424. EXPECT_THROW(parse("ThisIsWrong"), std::runtime_error);
  425. EXPECT_THROW(parse("34-2"), std::runtime_error);
  426. EXPECT_THROW(parse(""), std::runtime_error);
  427. EXPECT_THROW(parse("-"), std::runtime_error);
  428. EXPECT_THROW(parse("34-e2"), std::runtime_error);
  429. EXPECT_THROW(parse("34e2.4"), std::runtime_error);
  430. EXPECT_THROW(parse("infinity"), std::runtime_error);
  431. EXPECT_THROW(parse("nan"), std::runtime_error);
  432. }
  433. TEST(Json, SortKeys) {
  434. folly::json::serialization_opts opts_on, opts_off, opts_custom_sort;
  435. opts_on.sort_keys = true;
  436. opts_off.sort_keys = false;
  437. opts_custom_sort.sort_keys = false; // should not be required
  438. opts_custom_sort.sort_keys_by = [](folly::dynamic const& a,
  439. folly::dynamic const& b) {
  440. // just an inverse sort
  441. return b < a;
  442. };
  443. // clang-format off
  444. dynamic value = dynamic::object
  445. ("foo", "bar")
  446. ("junk", 12)
  447. ("another", 32.2)
  448. ("a",
  449. dynamic::array(
  450. dynamic::object("a", "b")("c", "d"),
  451. 12.5,
  452. "Yo Dawg",
  453. dynamic::array("heh"),
  454. nullptr));
  455. // clang-format on
  456. std::string sorted_keys =
  457. R"({"a":[{"a":"b","c":"d"},12.5,"Yo Dawg",["heh"],null],)"
  458. R"("another":32.2,"foo":"bar","junk":12})";
  459. std::string inverse_sorted_keys =
  460. R"({"junk":12,"foo":"bar","another":32.2,)"
  461. R"("a":[{"c":"d","a":"b"},12.5,"Yo Dawg",["heh"],null]})";
  462. EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_on)));
  463. EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_off)));
  464. EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_custom_sort)));
  465. EXPECT_EQ(sorted_keys, folly::json::serialize(value, opts_on));
  466. EXPECT_NE(sorted_keys, folly::json::serialize(value, opts_off));
  467. EXPECT_EQ(
  468. inverse_sorted_keys, folly::json::serialize(value, opts_custom_sort));
  469. }
  470. TEST(Json, PrintTo) {
  471. std::ostringstream oss;
  472. // clang-format off
  473. dynamic value = dynamic::object
  474. ("foo", "bar")
  475. ("junk", 12)
  476. ("another", 32.2)
  477. (true, false) // include non-string keys
  478. (false, true)
  479. (2, 3)
  480. (0, 1)
  481. (1, 2)
  482. (1.5, 2.25)
  483. (0.5, 0.25)
  484. (0, 1)
  485. (1, 2)
  486. ("a",
  487. dynamic::array(
  488. dynamic::object("a", "b")
  489. ("c", "d"),
  490. 12.5,
  491. "Yo Dawg",
  492. dynamic::array("heh"),
  493. nullptr
  494. )
  495. )
  496. ;
  497. // clang-format on
  498. std::string expected =
  499. R"({
  500. false: true,
  501. true: false,
  502. 0.5: 0.25,
  503. 1.5: 2.25,
  504. 0: 1,
  505. 1: 2,
  506. 2: 3,
  507. "a": [
  508. {
  509. "a": "b",
  510. "c": "d"
  511. },
  512. 12.5,
  513. "Yo Dawg",
  514. [
  515. "heh"
  516. ],
  517. null
  518. ],
  519. "another": 32.2,
  520. "foo": "bar",
  521. "junk": 12
  522. })";
  523. PrintTo(value, &oss);
  524. EXPECT_EQ(expected, oss.str());
  525. }
  526. TEST(Json, RecursionLimit) {
  527. std::string in;
  528. for (int i = 0; i < 1000; i++) {
  529. in.append("{\"x\":");
  530. }
  531. in.append("\"hi\"");
  532. for (int i = 0; i < 1000; i++) {
  533. in.append("}");
  534. }
  535. EXPECT_ANY_THROW(parseJson(in));
  536. folly::json::serialization_opts opts_high_recursion_limit;
  537. opts_high_recursion_limit.recursion_limit = 10000;
  538. parseJson(in, opts_high_recursion_limit);
  539. }
  540. TEST(Json, ExtraEscapes) {
  541. folly::json::serialization_opts opts;
  542. dynamic in = dynamic::object("a", "<foo@bar%baz?>");
  543. // Only in second index, only first bit of that index.
  544. opts.extra_ascii_to_escape_bitmap =
  545. folly::json::buildExtraAsciiToEscapeBitmap("@");
  546. auto serialized = folly::json::serialize(in, opts);
  547. EXPECT_EQ("{\"a\":\"<foo\\u0040bar%baz?>\"}", serialized);
  548. EXPECT_EQ(in, folly::parseJson(serialized));
  549. // Only last bit.
  550. opts.extra_ascii_to_escape_bitmap =
  551. folly::json::buildExtraAsciiToEscapeBitmap("?");
  552. serialized = folly::json::serialize(in, opts);
  553. EXPECT_EQ("{\"a\":\"<foo@bar%baz\\u003f>\"}", serialized);
  554. EXPECT_EQ(in, folly::parseJson(serialized));
  555. // Multiple bits.
  556. opts.extra_ascii_to_escape_bitmap =
  557. folly::json::buildExtraAsciiToEscapeBitmap("<%@?");
  558. serialized = folly::json::serialize(in, opts);
  559. EXPECT_EQ("{\"a\":\"\\u003cfoo\\u0040bar\\u0025baz\\u003f>\"}", serialized);
  560. EXPECT_EQ(in, folly::parseJson(serialized));
  561. // Non-ASCII
  562. in = dynamic::object("a", "a\xe0\xa0\x80z\xc0\x80");
  563. opts.extra_ascii_to_escape_bitmap =
  564. folly::json::buildExtraAsciiToEscapeBitmap("@");
  565. serialized = folly::json::serialize(in, opts);
  566. EXPECT_EQ("{\"a\":\"a\xe0\xa0\x80z\xc0\x80\"}", serialized);
  567. EXPECT_EQ(in, folly::parseJson(serialized));
  568. }
  569. TEST(Json, CharsToUnicodeEscape) {
  570. auto testPair = [](std::array<uint64_t, 2> arr, uint64_t zero, uint64_t one) {
  571. EXPECT_EQ(zero, arr[0]);
  572. EXPECT_EQ(one, arr[1]);
  573. };
  574. testPair(folly::json::buildExtraAsciiToEscapeBitmap(""), 0, 0);
  575. // ?=63
  576. testPair(folly::json::buildExtraAsciiToEscapeBitmap("?"), (1UL << 63), 0);
  577. // @=64
  578. testPair(
  579. folly::json::buildExtraAsciiToEscapeBitmap("@"), 0, (1UL << (64 - 64)));
  580. testPair(
  581. folly::json::buildExtraAsciiToEscapeBitmap("?@"),
  582. (1UL << 63),
  583. (1UL << (64 - 64)));
  584. testPair(
  585. folly::json::buildExtraAsciiToEscapeBitmap("@?"),
  586. (1UL << 63),
  587. (1UL << (64 - 64)));
  588. // duplicates
  589. testPair(
  590. folly::json::buildExtraAsciiToEscapeBitmap("@?@?"),
  591. (1UL << 63),
  592. (1UL << (64 - 64)));
  593. // ?=63, @=64, $=36
  594. testPair(
  595. folly::json::buildExtraAsciiToEscapeBitmap("?@$"),
  596. (1UL << 63) | (1UL << 36),
  597. (1UL << (64 - 64)));
  598. // ?=63, $=36, @=64, !=33
  599. testPair(
  600. folly::json::buildExtraAsciiToEscapeBitmap("?@$!"),
  601. (1UL << 63) | (1UL << 36) | (1UL << 33),
  602. (1UL << (64 - 64)));
  603. // ?=63, $=36, @=64, !=33, ]=93
  604. testPair(
  605. folly::json::buildExtraAsciiToEscapeBitmap("?@$!]"),
  606. (1UL << 63) | (1UL << 36) | (1UL << 33),
  607. (1UL << (64 - 64)) | (1UL << (93 - 64)));
  608. }