2 * Copyright 2016 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <boost/next_prior.hpp>
19 #include <folly/json.h>
20 #include <gtest/gtest.h>
23 using folly::parseJson;
27 auto val = parseJson(u8"\"I \u2665 UTF-8\"");
28 EXPECT_EQ(u8"I \u2665 UTF-8", val.asString());
29 val = parseJson("\"I \\u2665 UTF-8\"");
30 EXPECT_EQ(u8"I \u2665 UTF-8", val.asString());
31 val = parseJson(u8"\"I \U0001D11E playing in G-clef\"");
32 EXPECT_EQ(u8"I \U0001D11E playing in G-clef", val.asString());
34 val = parseJson("\"I \\uD834\\uDD1E playing in G-clef\"");
35 EXPECT_EQ(u8"I \U0001D11E playing in G-clef", val.asString());
39 auto num = parseJson("12");
40 EXPECT_TRUE(num.isInt());
42 num = parseJson("12e5");
43 EXPECT_TRUE(num.isDouble());
45 auto numAs1 = num.asDouble();
46 EXPECT_EQ(numAs1, 12e5);
48 EXPECT_EQ(num, 1200000);
50 auto largeNumber = parseJson("4611686018427387904");
51 EXPECT_TRUE(largeNumber.isInt());
52 EXPECT_EQ(largeNumber, 4611686018427387904L);
54 auto negative = parseJson("-123");
55 EXPECT_EQ(negative, -123);
57 auto bfalse = parseJson("false");
58 auto btrue = parseJson("true");
59 EXPECT_EQ(bfalse, false);
60 EXPECT_EQ(btrue, true);
62 auto null = parseJson("null");
63 EXPECT_TRUE(null == nullptr);
65 auto doub1 = parseJson("12.0");
66 auto doub2 = parseJson("12e2");
67 EXPECT_EQ(doub1, 12.0);
68 EXPECT_EQ(doub2, 12e2);
69 EXPECT_EQ(std::numeric_limits<double>::infinity(),
70 parseJson("Infinity").asDouble());
71 EXPECT_EQ(-std::numeric_limits<double>::infinity(),
72 parseJson("-Infinity").asDouble());
73 EXPECT_TRUE(std::isnan(parseJson("NaN").asDouble()));
76 EXPECT_THROW(parseJson("infinity"), std::runtime_error);
77 EXPECT_THROW(parseJson("inf"), std::runtime_error);
78 EXPECT_THROW(parseJson("Inf"), std::runtime_error);
79 EXPECT_THROW(parseJson("INF"), std::runtime_error);
80 EXPECT_THROW(parseJson("nan"), std::runtime_error);
81 EXPECT_THROW(parseJson("NAN"), std::runtime_error);
83 auto array = parseJson(
84 "[12,false, false , null , [12e4,32, [], 12]]");
85 EXPECT_EQ(array.size(), 5);
86 if (array.size() == 5) {
87 EXPECT_EQ(boost::prior(array.end())->size(), 4);
90 EXPECT_THROW(parseJson("\n[12,\n\nnotvalidjson"),
93 EXPECT_THROW(parseJson("12e2e2"),
96 EXPECT_THROW(parseJson("{\"foo\":12,\"bar\":42} \"something\""),
99 dynamic value = dynamic::object
105 dynamic::object("a", "b")
109 dynamic::array("heh"),
115 // Print then parse and get the same thing, hopefully.
116 EXPECT_EQ(value, parseJson(toJson(value)));
119 // Test an object with non-string values.
120 dynamic something = parseJson(
121 "{\"old_value\":40,\"changed\":true,\"opened\":false}");
122 dynamic expected = dynamic::object
126 EXPECT_EQ(something, expected);
129 TEST(Json, ParseTrailingComma) {
130 folly::json::serialization_opts on, off;
131 on.allow_trailing_comma = true;
132 off.allow_trailing_comma = false;
134 dynamic arr = dynamic::array(1, 2);
135 EXPECT_EQ(arr, parseJson("[1, 2]", on));
136 EXPECT_EQ(arr, parseJson("[1, 2,]", on));
137 EXPECT_EQ(arr, parseJson("[1, 2, ]", on));
138 EXPECT_EQ(arr, parseJson("[1, 2 , ]", on));
139 EXPECT_EQ(arr, parseJson("[1, 2 ,]", on));
140 EXPECT_THROW(parseJson("[1, 2,]", off), std::runtime_error);
142 dynamic obj = dynamic::object("a", 1);
143 EXPECT_EQ(obj, parseJson("{\"a\": 1}", on));
144 EXPECT_EQ(obj, parseJson("{\"a\": 1,}", on));
145 EXPECT_EQ(obj, parseJson("{\"a\": 1, }", on));
146 EXPECT_EQ(obj, parseJson("{\"a\": 1 , }", on));
147 EXPECT_EQ(obj, parseJson("{\"a\": 1 ,}", on));
148 EXPECT_THROW(parseJson("{\"a\":1,}", off), std::runtime_error);
151 TEST(Json, BoolConversion) {
152 EXPECT_TRUE(parseJson("42").asBool());
155 TEST(Json, JavascriptSafe) {
156 auto badDouble = (1ll << 63ll) + 1;
157 dynamic badDyn = badDouble;
158 EXPECT_EQ(folly::toJson(badDouble), folly::to<std::string>(badDouble));
159 folly::json::serialization_opts opts;
160 opts.javascript_safe = true;
161 EXPECT_ANY_THROW(folly::json::serialize(badDouble, opts));
163 auto okDouble = 1ll << 63ll;
164 dynamic okDyn = okDouble;
165 EXPECT_EQ(folly::toJson(okDouble), folly::to<std::string>(okDouble));
168 TEST(Json, Produce) {
169 auto value = parseJson(R"( "f\"oo" )");
170 EXPECT_EQ(toJson(value), R"("f\"oo")");
171 value = parseJson("\"Control code: \001 \002 \x1f\"");
172 EXPECT_EQ(toJson(value), R"("Control code: \u0001 \u0002 \u001f")");
174 // We're not allowed to have non-string keys in json.
175 EXPECT_THROW(toJson(dynamic::object("abc", "xyz")(42.33, "asd")),
178 // Check Infinity/Nan
179 folly::json::serialization_opts opts;
180 opts.allow_nan_inf = true;
181 EXPECT_EQ("Infinity", folly::json::serialize(parseJson("Infinity"), opts));
182 EXPECT_EQ("NaN", folly::json::serialize(parseJson("NaN"), opts));
185 TEST(Json, JsonEscape) {
186 folly::json::serialization_opts opts;
188 folly::json::serialize("\b\f\n\r\x01\t\\\"/\v\a", opts),
189 R"("\b\f\n\r\u0001\t\\\"/\u000b\u0007")");
192 TEST(Json, JsonNonAsciiEncoding) {
193 folly::json::serialization_opts opts;
194 opts.encode_non_ascii = true;
197 EXPECT_EQ(folly::json::serialize("\x1f", opts), R"("\u001f")");
198 EXPECT_EQ(folly::json::serialize("\xc2\xa2", opts), R"("\u00a2")");
199 EXPECT_EQ(folly::json::serialize("\xe2\x82\xac", opts), R"("\u20ac")");
201 // multiple unicode encodings
203 folly::json::serialize("\x1f\xe2\x82\xac", opts),
204 R"("\u001f\u20ac")");
206 folly::json::serialize("\x1f\xc2\xa2\xe2\x82\xac", opts),
207 R"("\u001f\u00a2\u20ac")");
209 folly::json::serialize("\xc2\x80\xef\xbf\xbf", opts),
210 R"("\u0080\uffff")");
212 folly::json::serialize("\xe0\xa0\x80\xdf\xbf", opts),
213 R"("\u0800\u07ff")");
215 // first possible sequence of a certain length
216 EXPECT_EQ(folly::json::serialize("\xc2\x80", opts), R"("\u0080")");
217 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")");
223 // other boundary conditions
224 EXPECT_EQ(folly::json::serialize("\xed\x9f\xbf", opts), R"("\ud7ff")");
225 EXPECT_EQ(folly::json::serialize("\xee\x80\x80", opts), R"("\ue000")");
226 EXPECT_EQ(folly::json::serialize("\xef\xbf\xbd", opts), R"("\ufffd")");
228 // incomplete sequences
229 EXPECT_ANY_THROW(folly::json::serialize("a\xed\x9f", opts));
230 EXPECT_ANY_THROW(folly::json::serialize("b\xee\x80", opts));
231 EXPECT_ANY_THROW(folly::json::serialize("c\xef\xbf", opts));
234 EXPECT_ANY_THROW(folly::json::serialize("\xfe", opts));
235 EXPECT_ANY_THROW(folly::json::serialize("\xff", opts));
237 // Sample overlong sequences
238 EXPECT_ANY_THROW(folly::json::serialize("\xc0\xaf", opts));
239 EXPECT_ANY_THROW(folly::json::serialize("\xe0\x80\xaf", opts));
241 // Maximum overlong sequences
242 EXPECT_ANY_THROW(folly::json::serialize("\xc1\xbf", opts));
243 EXPECT_ANY_THROW(folly::json::serialize("\x30\x9f\xbf", opts));
245 // illegal code positions
246 EXPECT_ANY_THROW(folly::json::serialize("\xed\xa0\x80", opts));
247 EXPECT_ANY_THROW(folly::json::serialize("\xed\xbf\xbf", opts));
249 // Overlong representation of NUL character
250 EXPECT_ANY_THROW(folly::json::serialize("\xc0\x80", opts));
251 EXPECT_ANY_THROW(folly::json::serialize("\xe0\x80\x80", opts));
253 // Longer than 3 byte encodings
254 EXPECT_ANY_THROW(folly::json::serialize("\xf4\x8f\xbf\xbf", opts));
255 EXPECT_ANY_THROW(folly::json::serialize("\xed\xaf\xbf\xed\xbf\xbf", opts));
258 TEST(Json, UTF8Retention) {
260 // test retention with valid utf8 strings
261 std::string input = u8"\u2665";
262 std::string jsonInput = folly::toJson(input);
263 std::string output = folly::parseJson(jsonInput).asString();
264 std::string jsonOutput = folly::toJson(output);
266 EXPECT_EQ(input, output);
267 EXPECT_EQ(jsonInput, jsonOutput);
269 // test retention with invalid utf8 - note that non-ascii chars are retained
270 // as is, and no unicode encoding is attempted so no exception is thrown.
272 folly::toJson("a\xe0\xa0\x80z\xc0\x80"),
273 "\"a\xe0\xa0\x80z\xc0\x80\""
277 TEST(Json, UTF8EncodeNonAsciiRetention) {
279 folly::json::serialization_opts opts;
280 opts.encode_non_ascii = true;
282 // test encode_non_ascii valid utf8 strings
283 std::string input = u8"\u2665";
284 std::string jsonInput = folly::json::serialize(input, opts);
285 std::string output = folly::parseJson(jsonInput).asString();
286 std::string jsonOutput = folly::json::serialize(output, opts);
288 EXPECT_EQ(input, output);
289 EXPECT_EQ(jsonInput, jsonOutput);
291 // test encode_non_ascii with invalid utf8 - note that an attempt to encode
292 // non-ascii to unicode will result is a utf8 validation and throw exceptions.
293 EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts));
294 EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xe0\x80\x80", opts));
297 TEST(Json, UTF8Validation) {
298 folly::json::serialization_opts opts;
299 opts.validate_utf8 = true;
301 // test validate_utf8 valid utf8 strings - note that we only validate the
302 // for utf8 but don't encode non-ascii to unicode so they are retained as is.
303 EXPECT_EQ(folly::json::serialize("a\xc2\x80z", opts), "\"a\xc2\x80z\"");
305 folly::json::serialize("a\xe0\xa0\x80z", opts),
306 "\"a\xe0\xa0\x80z\"");
308 folly::json::serialize("a\xe0\xa0\x80m\xc2\x80z", opts),
309 "\"a\xe0\xa0\x80m\xc2\x80z\"");
311 // test validate_utf8 with invalid utf8
312 EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts));
313 EXPECT_ANY_THROW(folly::json::serialize("a\xe0\xa0\x80z\xe0\x80\x80", opts));
315 opts.skip_invalid_utf8 = true;
317 folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts),
318 u8"\"a\xe0\xa0\x80z\ufffd\ufffd\"");
320 folly::json::serialize("a\xe0\xa0\x80z\xc0\x80\x80", opts),
321 u8"\"a\xe0\xa0\x80z\ufffd\ufffd\ufffd\"");
323 folly::json::serialize("z\xc0\x80z\xe0\xa0\x80", opts),
324 u8"\"z\ufffd\ufffdz\xe0\xa0\x80\"");
326 opts.encode_non_ascii = true;
327 EXPECT_EQ(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80", opts),
328 "\"a\\u0800z\\ufffd\\ufffd\"");
329 EXPECT_EQ(folly::json::serialize("a\xe0\xa0\x80z\xc0\x80\x80", opts),
330 "\"a\\u0800z\\ufffd\\ufffd\\ufffd\"");
331 EXPECT_EQ(folly::json::serialize("z\xc0\x80z\xe0\xa0\x80", opts),
332 "\"z\\ufffd\\ufffdz\\u0800\"");
337 TEST(Json, ParseNonStringKeys) {
339 EXPECT_EQ("a", parseJson("{\"a\":[]}").items().begin()->first.asString());
341 // check that we don't allow non-string keys as this violates the
342 // strict JSON spec (though it is emitted by the output of
343 // folly::dynamic with operator <<).
344 EXPECT_THROW(parseJson("{1:[]}"), std::runtime_error);
346 // check that we can parse colloquial JSON if the option is set
347 folly::json::serialization_opts opts;
348 opts.allow_non_string_keys = true;
350 auto val = parseJson("{1:[]}", opts);
351 EXPECT_EQ(1, val.items().begin()->first.asInt());
354 // test we can still read in strings
355 auto sval = parseJson("{\"a\":[]}", opts);
356 EXPECT_EQ("a", sval.items().begin()->first.asString());
358 // test we can read in doubles
359 auto dval = parseJson("{1.5:[]}", opts);
360 EXPECT_EQ(1.5, dval.items().begin()->first.asDouble());
363 TEST(Json, ParseDoubleFallback) {
365 EXPECT_THROW(parseJson("{\"a\":847605071342477600000000000000}"),
367 EXPECT_THROW(parseJson("{\"a\":-9223372036854775809}"),
369 EXPECT_THROW(parseJson("{\"a\":9223372036854775808}"),
371 EXPECT_EQ(std::numeric_limits<int64_t>::min(),
372 parseJson("{\"a\":-9223372036854775808}").items().begin()
374 EXPECT_EQ(std::numeric_limits<int64_t>::max(),
375 parseJson("{\"a\":9223372036854775807}").items().begin()->second.asInt());
376 // with double_fallback
377 folly::json::serialization_opts opts;
378 opts.double_fallback = true;
379 EXPECT_EQ(847605071342477600000000000000.0,
380 parseJson("{\"a\":847605071342477600000000000000}",
381 opts).items().begin()->second.asDouble());
382 EXPECT_EQ(847605071342477600000000000000.0,
383 parseJson("{\"a\": 847605071342477600000000000000}",
384 opts).items().begin()->second.asDouble());
385 EXPECT_EQ(847605071342477600000000000000.0,
386 parseJson("{\"a\":847605071342477600000000000000 }",
387 opts).items().begin()->second.asDouble());
388 EXPECT_EQ(847605071342477600000000000000.0,
389 parseJson("{\"a\": 847605071342477600000000000000 }",
390 opts).items().begin()->second.asDouble());
391 EXPECT_EQ(std::numeric_limits<int64_t>::min(),
392 parseJson("{\"a\":-9223372036854775808}",
393 opts).items().begin()->second.asInt());
394 EXPECT_EQ(std::numeric_limits<int64_t>::max(),
395 parseJson("{\"a\":9223372036854775807}",
396 opts).items().begin()->second.asInt());
397 // show that some precision gets lost
398 EXPECT_EQ(847605071342477612345678900000.0,
399 parseJson("{\"a\":847605071342477612345678912345}",
400 opts).items().begin()->second.asDouble());
402 toJson(parseJson(R"({"a":-9223372036854775808})", opts)),
403 R"({"a":-9223372036854775808})");
406 TEST(Json, ParseNumbersAsStrings) {
407 folly::json::serialization_opts opts;
408 opts.parse_numbers_as_strings = true;
409 auto parse = [&](std::string number) {
410 return parseJson(number, opts).asString();
413 EXPECT_EQ("0", parse("0"));
414 EXPECT_EQ("1234", parse("1234"));
415 EXPECT_EQ("3.00", parse("3.00"));
416 EXPECT_EQ("3.14", parse("3.14"));
417 EXPECT_EQ("0.1234", parse("0.1234"));
418 EXPECT_EQ("0.0", parse("0.0"));
419 EXPECT_EQ("46845131213548676854213265486468451312135486768542132",
420 parse("46845131213548676854213265486468451312135486768542132"));
421 EXPECT_EQ("-468451312135486768542132654864684513121354867685.5e4",
422 parse("-468451312135486768542132654864684513121354867685.5e4"));
423 EXPECT_EQ("6.62607004e-34", parse("6.62607004e-34"));
424 EXPECT_EQ("6.62607004E+34", parse("6.62607004E+34"));
425 EXPECT_EQ("Infinity", parse("Infinity"));
426 EXPECT_EQ("-Infinity", parse("-Infinity"));
427 EXPECT_EQ("NaN", parse("NaN"));
429 EXPECT_THROW(parse("ThisIsWrong"), std::runtime_error);
430 EXPECT_THROW(parse("34-2"), std::runtime_error);
431 EXPECT_THROW(parse(""), std::runtime_error);
432 EXPECT_THROW(parse("-"), std::runtime_error);
433 EXPECT_THROW(parse("34-e2"), std::runtime_error);
434 EXPECT_THROW(parse("34e2.4"), std::runtime_error);
435 EXPECT_THROW(parse("infinity"), std::runtime_error);
436 EXPECT_THROW(parse("nan"), std::runtime_error);
439 TEST(Json, SortKeys) {
440 folly::json::serialization_opts opts_on, opts_off;
441 opts_on.sort_keys = true;
442 opts_off.sort_keys = false;
444 dynamic value = dynamic::object
450 dynamic::object("a", "b")
454 dynamic::array("heh"),
460 std::string sorted_keys =
461 R"({"a":[{"a":"b","c":"d"},12.5,"Yo Dawg",["heh"],null],)"
462 R"("another":32.2,"foo":"bar","junk":12})";
464 EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_on)));
465 EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_off)));
467 EXPECT_EQ(sorted_keys, folly::json::serialize(value, opts_on));
470 TEST(Json, PrintTo) {
471 std::ostringstream oss;
473 dynamic value = dynamic::object
477 (true, false) // include non-string keys
488 dynamic::object("a", "b")
492 dynamic::array("heh"),
498 std::string expected =
523 PrintTo(value, &oss);
524 EXPECT_EQ(expected, oss.str());
527 TEST(Json, RecursionLimit) {
529 for (int i = 0; i < 1000; i++) {
530 in.append("{\"x\":");
533 for (int i = 0; i < 1000; i++) {
536 EXPECT_ANY_THROW(parseJson(in));
538 folly::json::serialization_opts opts_high_recursion_limit;
539 opts_high_recursion_limit.recursion_limit = 10000;
540 parseJson(in, opts_high_recursion_limit);