sort_keys option for json
[folly.git] / folly / json.cpp
1 /*
2  * Copyright 2013 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
17 #include "folly/json.h"
18 #include <cassert>
19 #include <boost/next_prior.hpp>
20 #include <boost/algorithm/string.hpp>
21
22 #include "folly/Range.h"
23 #include "folly/Unicode.h"
24 #include "folly/Conv.h"
25
26 namespace folly {
27
28 //////////////////////////////////////////////////////////////////////
29
30 namespace json {
31 namespace {
32
33 char32_t decodeUtf8(const unsigned char*& p, const unsigned char* const e) {
34   /* The following encodings are valid, except for the 5 and 6 byte
35    * combinations:
36    * 0xxxxxxx
37    * 110xxxxx 10xxxxxx
38    * 1110xxxx 10xxxxxx 10xxxxxx
39    * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
40    * 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
41    * 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
42    */
43
44   if (p >= e) {
45     throw std::runtime_error("folly::decodeUtf8 empty/invalid string");
46   }
47
48   unsigned char fst = *p;
49   if (!(fst & 0x80)) {
50     // trivial case
51     return *p++;
52   }
53
54   static const uint32_t bitMask[] = {
55     (1 << 7) - 1,
56     (1 << 11) - 1,
57     (1 << 16) - 1,
58     (1 << 21) - 1
59   };
60
61   // upper control bits are masked out later
62   uint32_t d = fst;
63
64   if ((fst & 0xC0) != 0xC0) {
65     throw std::runtime_error(
66       to<std::string>("folly::decodeUtf8 i=0 d=", d));
67   }
68
69   fst <<= 1;
70
71   for (unsigned int i = 1; i != 3 && p + i < e; ++i) {
72     unsigned char tmp = p[i];
73
74     if ((tmp & 0xC0) != 0x80) {
75       throw std::runtime_error(
76         to<std::string>("folly::decodeUtf8 i=", i, " tmp=", (uint32_t)tmp));
77     }
78
79     d = (d << 6) | (tmp & 0x3F);
80     fst <<= 1;
81
82     if (!(fst & 0x80)) {
83       d &= bitMask[i];
84
85       // overlong, could have been encoded with i bytes
86       if ((d & ~bitMask[i - 1]) == 0) {
87         throw std::runtime_error(
88           to<std::string>("folly::decodeUtf8 i=", i, " d=", d));
89       }
90
91       // check for surrogates only needed for 3 bytes
92       if (i == 2) {
93         if ((d >= 0xD800 && d <= 0xDFFF) || d > 0x10FFFF) {
94           throw std::runtime_error(
95             to<std::string>("folly::decodeUtf8 i=", i, " d=", d));
96         }
97       }
98
99       p += i + 1;
100       return d;
101     }
102   }
103
104   throw std::runtime_error("folly::decodeUtf8 encoding length maxed out");
105 }
106
107 struct Printer {
108   explicit Printer(fbstring& out,
109                    unsigned* indentLevel,
110                    serialization_opts const* opts)
111     : out_(out)
112     , indentLevel_(indentLevel)
113     , opts_(*opts)
114   {}
115
116   void operator()(dynamic const& v) const {
117     switch (v.type()) {
118     case dynamic::DOUBLE:
119       toAppend(v.asDouble(), &out_);
120       break;
121     case dynamic::INT64: {
122       auto intval = v.asInt();
123       if (opts_.javascript_safe) {
124         // Use folly::to to check that this integer can be represented
125         // as a double without loss of precision.
126         intval = int64_t(to<double>(intval));
127       }
128       toAppend(intval, &out_);
129       break;
130     }
131     case dynamic::BOOL:
132       out_ += v.asBool() ? "true" : "false";
133       break;
134     case dynamic::NULLT:
135       out_ += "null";
136       break;
137     case dynamic::STRING:
138       escapeString(v.asString(), out_, opts_);
139       break;
140     case dynamic::OBJECT:
141       printObject(v);
142       break;
143     case dynamic::ARRAY:
144       printArray(v);
145       break;
146     default:
147       CHECK(0) << "Bad type " << v.type();
148     }
149   }
150
151 private:
152   void printKV(const std::pair<const dynamic, dynamic>& p) const {
153     if (!opts_.allow_non_string_keys && !p.first.isString()) {
154       throw std::runtime_error("folly::toJson: JSON object key was not a "
155         "string");
156     }
157     (*this)(p.first);
158     mapColon();
159     (*this)(p.second);
160   }
161
162   template <typename Iterator>
163   void printKVPairs(Iterator begin, Iterator end) const {
164     printKV(*begin);
165     for (++begin; begin != end; ++begin) {
166       out_ += ',';
167       newline();
168       printKV(*begin);
169     }
170   }
171
172   void printObject(dynamic const& o) const {
173     if (o.empty()) {
174       out_ += "{}";
175       return;
176     }
177
178     out_ += '{';
179     indent();
180     newline();
181     if (opts_.sort_keys) {
182       std::vector<std::pair<dynamic, dynamic>> items(
183         o.items().begin(), o.items().end());
184       std::sort(items.begin(), items.end());
185       printKVPairs(items.begin(), items.end());
186     } else {
187       printKVPairs(o.items().begin(), o.items().end());
188     }
189     outdent();
190     newline();
191     out_ += '}';
192   }
193
194   void printArray(dynamic const& a) const {
195     if (a.empty()) {
196       out_ += "[]";
197       return;
198     }
199
200     out_ += '[';
201     indent();
202     newline();
203     (*this)(a[0]);
204     for (auto& val : makeRange(boost::next(a.begin()), a.end())) {
205       out_ += ',';
206       newline();
207       (*this)(val);
208     }
209     outdent();
210     newline();
211     out_ += ']';
212   }
213
214 private:
215   void outdent() const {
216     if (indentLevel_) {
217       --*indentLevel_;
218     }
219   }
220
221   void indent() const {
222     if (indentLevel_) {
223       ++*indentLevel_;
224     }
225   }
226
227   void newline() const {
228     if (indentLevel_) {
229       out_ += to<fbstring>('\n', fbstring(*indentLevel_ * 2, ' '));
230     }
231   }
232
233   void mapColon() const {
234     out_ += indentLevel_ ? " : " : ":";
235   }
236
237 private:
238   fbstring& out_;
239   unsigned* const indentLevel_;
240   serialization_opts const& opts_;
241 };
242
243 //////////////////////////////////////////////////////////////////////
244
245 struct ParseError : std::runtime_error {
246   explicit ParseError(int line)
247     : std::runtime_error(to<std::string>("json parse error on line ", line))
248   {}
249
250   explicit ParseError(int line, std::string const& context,
251       std::string const& expected)
252     : std::runtime_error(to<std::string>("json parse error on line ", line,
253         !context.empty() ? to<std::string>(" near `", context, '\'')
254                         : "",
255         ": ", expected))
256   {}
257
258   explicit ParseError(std::string const& what)
259     : std::runtime_error("json parse error: " + what)
260   {}
261 };
262
263 // Wraps our input buffer with some helper functions.
264 struct Input {
265   explicit Input(StringPiece range, json::serialization_opts const* opts)
266       : range_(range)
267       , opts_(*opts)
268       , lineNum_(0)
269   {
270     storeCurrent();
271   }
272
273   Input(Input const&) = delete;
274   Input& operator=(Input const&) = delete;
275
276   char const* begin() const { return range_.begin(); }
277
278   // Parse ahead for as long as the supplied predicate is satisfied,
279   // returning a range of what was skipped.
280   template<class Predicate>
281   StringPiece skipWhile(const Predicate& p) {
282     std::size_t skipped = 0;
283     for (; skipped < range_.size(); ++skipped) {
284       if (!p(range_[skipped])) {
285         break;
286       }
287       if (range_[skipped] == '\n') {
288         ++lineNum_;
289       }
290     }
291     auto ret = range_.subpiece(0, skipped);
292     range_.advance(skipped);
293     storeCurrent();
294     return ret;
295   }
296
297   StringPiece skipDigits() {
298     return skipWhile([] (char c) { return c >= '0' && c <= '9'; });
299   }
300
301   void skipWhitespace() {
302     // Spaces other than ' ' characters are less common but should be
303     // checked.  This configuration where we loop on the ' '
304     // separately from oddspaces was empirically fastest.
305     auto oddspace = [] (char c) {
306       return c == '\n' || c == '\t' || c == '\r';
307     };
308
309   loop:
310     for (; !range_.empty() && range_.front() == ' '; range_.pop_front()) {
311     }
312     if (!range_.empty() && oddspace(range_.front())) {
313       range_.pop_front();
314       goto loop;
315     }
316     storeCurrent();
317   }
318
319   void expect(char c) {
320     if (**this != c) {
321       throw ParseError(lineNum_, context(),
322         to<std::string>("expected '", c, '\''));
323     }
324     ++*this;
325   }
326
327   std::size_t size() const {
328     return range_.size();
329   }
330
331   int operator*() const {
332     return current_;
333   }
334
335   void operator++() {
336     range_.pop_front();
337     storeCurrent();
338   }
339
340   template<class T>
341   T extract() {
342     try {
343       return to<T>(&range_);
344     } catch (std::exception const& e) {
345       error(e.what());
346     }
347   }
348
349   bool consume(StringPiece str) {
350     if (boost::starts_with(range_, str)) {
351       range_.advance(str.size());
352       storeCurrent();
353       return true;
354     }
355     return false;
356   }
357
358   std::string context() const {
359     return range_.subpiece(0, 16 /* arbitrary */).toString();
360   }
361
362   dynamic error(char const* what) const {
363     throw ParseError(lineNum_, context(), what);
364   }
365
366   json::serialization_opts const& getOpts() {
367     return opts_;
368   }
369
370 private:
371   void storeCurrent() {
372     current_ = range_.empty() ? EOF : range_.front();
373   }
374
375 private:
376   StringPiece range_;
377   json::serialization_opts const& opts_;
378   unsigned lineNum_;
379   int current_;
380 };
381
382 dynamic parseValue(Input& in);
383 fbstring parseString(Input& in);
384 dynamic parseNumber(Input& in);
385
386 dynamic parseObject(Input& in) {
387   assert(*in == '{');
388   ++in;
389
390   dynamic ret = dynamic::object;
391
392   in.skipWhitespace();
393   if (*in == '}') {
394     ++in;
395     return ret;
396   }
397
398   for (;;) {
399     if (in.getOpts().allow_trailing_comma && *in == '}') {
400       break;
401     }
402     if (*in == '\"') { // string
403       auto key = parseString(in);
404       in.skipWhitespace();
405       in.expect(':');
406       in.skipWhitespace();
407       ret.insert(std::move(key), parseValue(in));
408     } else if (!in.getOpts().allow_non_string_keys) {
409       in.error("expected string for object key name");
410     } else {
411       auto key = parseValue(in);
412       in.skipWhitespace();
413       in.expect(':');
414       in.skipWhitespace();
415       ret.insert(std::move(key), parseValue(in));
416     }
417
418     in.skipWhitespace();
419     if (*in != ',') {
420       break;
421     }
422     ++in;
423     in.skipWhitespace();
424   }
425   in.expect('}');
426
427   return ret;
428 }
429
430 dynamic parseArray(Input& in) {
431   assert(*in == '[');
432   ++in;
433
434   dynamic ret = {};
435
436   in.skipWhitespace();
437   if (*in == ']') {
438     ++in;
439     return ret;
440   }
441
442   for (;;) {
443     if (in.getOpts().allow_trailing_comma && *in == ']') {
444       break;
445     }
446     ret.push_back(parseValue(in));
447     in.skipWhitespace();
448     if (*in != ',') {
449       break;
450     }
451     ++in;
452     in.skipWhitespace();
453   }
454   in.expect(']');
455
456   return ret;
457 }
458
459 dynamic parseNumber(Input& in) {
460   bool const negative = (*in == '-');
461   if (negative) {
462     ++in;
463     if (in.consume("Infinity")) {
464       return -std::numeric_limits<double>::infinity();
465     }
466   }
467
468   auto integral = in.skipDigits();
469   if (integral.empty()) {
470     in.error("expected digits after `-'");
471   }
472   auto const wasE = *in == 'e' || *in == 'E';
473   if (*in != '.' && !wasE) {
474     auto val = to<int64_t>(integral);
475     if (negative) {
476       val = -val;
477     }
478     in.skipWhitespace();
479     return val;
480   }
481
482   auto end = !wasE ? (++in, in.skipDigits().end()) : in.begin();
483   if (*in == 'e' || *in == 'E') {
484     ++in;
485     if (*in == '+' || *in == '-') {
486       ++in;
487     }
488     auto expPart = in.skipDigits();
489     end = expPart.end();
490   }
491   auto fullNum = makeRange(integral.begin(), end);
492
493   auto val = to<double>(fullNum);
494   if (negative) {
495     val *= -1;
496   }
497   return val;
498 }
499
500 fbstring decodeUnicodeEscape(Input& in) {
501   auto hexVal = [&] (char c) -> unsigned {
502     return c >= '0' && c <= '9' ? c - '0' :
503            c >= 'a' && c <= 'f' ? c - 'a' + 10 :
504            c >= 'A' && c <= 'F' ? c - 'A' + 10 :
505            (in.error("invalid hex digit"), 0);
506   };
507
508   auto readHex = [&]() -> uint16_t {
509     if (in.size() < 4) {
510       in.error("expected 4 hex digits");
511     }
512
513     uint16_t ret = hexVal(*in) * 4096;
514     ++in;
515     ret += hexVal(*in) * 256;
516     ++in;
517     ret += hexVal(*in) * 16;
518     ++in;
519     ret += hexVal(*in);
520     ++in;
521     return ret;
522   };
523
524   /*
525    * If the value encoded is in the surrogate pair range, we need to
526    * make sure there is another escape that we can use also.
527    */
528   uint32_t codePoint = readHex();
529   if (codePoint >= 0xd800 && codePoint <= 0xdbff) {
530     if (!in.consume("\\u")) {
531       in.error("expected another unicode escape for second half of "
532         "surrogate pair");
533     }
534     uint16_t second = readHex();
535     if (second >= 0xdc00 && second <= 0xdfff) {
536       codePoint = 0x10000 + ((codePoint & 0x3ff) << 10) +
537                   (second & 0x3ff);
538     } else {
539       in.error("second character in surrogate pair is invalid");
540     }
541   } else if (codePoint >= 0xdc00 && codePoint <= 0xdfff) {
542     in.error("invalid unicode code point (in range [0xdc00,0xdfff])");
543   }
544
545   return codePointToUtf8(codePoint);
546 }
547
548 fbstring parseString(Input& in) {
549   assert(*in == '\"');
550   ++in;
551
552   fbstring ret;
553   for (;;) {
554     auto range = in.skipWhile(
555       [] (char c) { return c != '\"' && c != '\\'; }
556     );
557     ret.append(range.begin(), range.end());
558
559     if (*in == '\"') {
560       ++in;
561       break;
562     }
563     if (*in == '\\') {
564       ++in;
565       switch (*in) {
566       case '\"':    ret.push_back('\"'); ++in; break;
567       case '\\':    ret.push_back('\\'); ++in; break;
568       case '/':     ret.push_back('/');  ++in; break;
569       case 'b':     ret.push_back('\b'); ++in; break;
570       case 'f':     ret.push_back('\f'); ++in; break;
571       case 'n':     ret.push_back('\n'); ++in; break;
572       case 'r':     ret.push_back('\r'); ++in; break;
573       case 't':     ret.push_back('\t'); ++in; break;
574       case 'u':     ++in; ret += decodeUnicodeEscape(in); break;
575       default:      in.error(to<fbstring>("unknown escape ", *in,
576                                           " in string").c_str());
577       }
578       continue;
579     }
580     if (*in == EOF) {
581       in.error("unterminated string");
582     }
583     if (!*in) {
584       /*
585        * Apparently we're actually supposed to ban all control
586        * characters from strings.  This seems unnecessarily
587        * restrictive, so we're only banning zero bytes.  (Since the
588        * string is presumed to be UTF-8 encoded it's fine to just
589        * check this way.)
590        */
591       in.error("null byte in string");
592     }
593
594     ret.push_back(*in);
595     ++in;
596   }
597
598   return ret;
599 }
600
601 dynamic parseValue(Input& in) {
602   in.skipWhitespace();
603   return *in == '[' ? parseArray(in) :
604          *in == '{' ? parseObject(in) :
605          *in == '\"' ? parseString(in) :
606          (*in == '-' || (*in >= '0' && *in <= '9')) ? parseNumber(in) :
607          in.consume("true") ? true :
608          in.consume("false") ? false :
609          in.consume("null") ? nullptr :
610          in.consume("Infinity") ? std::numeric_limits<double>::infinity() :
611          in.consume("NaN") ? std::numeric_limits<double>::quiet_NaN() :
612          in.error("expected json value");
613 }
614
615 }
616
617 //////////////////////////////////////////////////////////////////////
618
619 fbstring serialize(dynamic const& dyn, serialization_opts const& opts) {
620   fbstring ret;
621   unsigned indentLevel = 0;
622   Printer p(ret, opts.pretty_formatting ? &indentLevel : nullptr, &opts);
623   p(dyn);
624   return ret;
625 }
626
627 // Escape a string so that it is legal to print it in JSON text.
628 void escapeString(StringPiece input,
629                   fbstring& out,
630                   const serialization_opts& opts) {
631   auto hexDigit = [] (int c) -> char {
632     return c < 10 ? c + '0' : c - 10 + 'a';
633   };
634
635   out.reserve(out.size() + input.size() + 2);
636   out.push_back('\"');
637
638   auto* p = reinterpret_cast<const unsigned char*>(input.begin());
639   auto* q = reinterpret_cast<const unsigned char*>(input.begin());
640   auto* e = reinterpret_cast<const unsigned char*>(input.end());
641
642   while (p < e) {
643     // Since non-ascii encoding inherently does utf8 validation
644     // we explicitly validate utf8 only if non-ascii encoding is disabled.
645     if (opts.validate_utf8 && !opts.encode_non_ascii) {
646       // to achieve better spatial and temporal coherence
647       // we do utf8 validation progressively along with the
648       // string-escaping instead of two separate passes
649
650       // as the encoding progresses, q will stay at or ahead of p
651       CHECK(q >= p);
652
653       // as p catches up with q, move q forward
654       if (q == p) {
655         // calling utf8_decode has the side effect of
656         // checking that utf8 encodings are valid
657         decodeUtf8(q, e);
658       }
659     }
660     if (opts.encode_non_ascii && (*p & 0x80)) {
661       // note that this if condition captures utf8 chars
662       // with value > 127, so size > 1 byte
663       char32_t v = decodeUtf8(p, e);
664       out.append("\\u");
665       out.push_back(hexDigit(v >> 12));
666       out.push_back(hexDigit((v >> 8) & 0x0f));
667       out.push_back(hexDigit((v >> 4) & 0x0f));
668       out.push_back(hexDigit(v & 0x0f));
669     } else if (*p == '\\' || *p == '\"') {
670       out.push_back('\\');
671       out.push_back(*p++);
672     } else if (*p <= 0x1f) {
673       switch (*p) {
674         case '\b': out.append("\\b"); p++; break;
675         case '\f': out.append("\\f"); p++; break;
676         case '\n': out.append("\\n"); p++; break;
677         case '\r': out.append("\\r"); p++; break;
678         case '\t': out.append("\\t"); p++; break;
679         default:
680           // note that this if condition captures non readable chars
681           // with value < 32, so size = 1 byte (e.g control chars).
682           out.append("\\u00");
683           out.push_back(hexDigit((*p & 0xf0) >> 4));
684           out.push_back(hexDigit(*p & 0xf));
685           p++;
686       }
687     } else {
688       out.push_back(*p++);
689     }
690   }
691
692   out.push_back('\"');
693 }
694
695 }
696
697 //////////////////////////////////////////////////////////////////////
698
699 dynamic parseJson(StringPiece range) {
700   return parseJson(range, json::serialization_opts());
701 }
702
703 dynamic parseJson(
704     StringPiece range,
705     json::serialization_opts const& opts) {
706
707   json::Input in(range, &opts);
708
709   auto ret = parseValue(in);
710   in.skipWhitespace();
711   if (in.size() && *in != '\0') {
712     in.error("parsing didn't consume all input");
713   }
714   return ret;
715 }
716
717 fbstring toJson(dynamic const& dyn) {
718   return json::serialize(dyn, json::serialization_opts());
719 }
720
721 fbstring toPrettyJson(dynamic const& dyn) {
722   json::serialization_opts opts;
723   opts.pretty_formatting = true;
724   return json::serialize(dyn, opts);
725 }
726
727 //////////////////////////////////////////////////////////////////////
728 // dynamic::print_as_pseudo_json() is implemented here for header
729 // ordering reasons (most of the dynamic implementation is in
730 // dynamic-inl.h, which we don't want to include json.h).
731
732 void dynamic::print_as_pseudo_json(std::ostream& out) const {
733   json::serialization_opts opts;
734   opts.allow_non_string_keys = true;
735   out << json::serialize(*this, opts);
736 }
737
738 //////////////////////////////////////////////////////////////////////
739
740 }