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
17/**
18 *
19 * Serialize and deserialize folly::dynamic values as JSON.
20 *
21 * Before you use this you should probably understand the basic
22 * concepts in the JSON type system:
23 *
24 * Value : String | Bool | Null | Object | Array | Number
25 * String : UTF-8 sequence
26 * Object : (String, Value) pairs, with unique String keys
27 * Array : ordered list of Values
28 * Null : null
29 * Bool : true | false
30 * Number : (representation unspecified)
31 *
32 * ... That's about it. For more information see http://json.org or
33 * look up RFC 4627.
34 *
35 * If your dynamic has anything illegal with regard to this type
36 * system, the serializer will throw.
37 *
38 * @author Jordan DeLong <delong.j@fb.com>
39 */
40
41#pragma once
42
43#include <iosfwd>
44#include <string>
45
46#include <folly/Function.h>
47#include <folly/Range.h>
48#include <folly/dynamic.h>
49
50namespace folly {
51
52//////////////////////////////////////////////////////////////////////
53
54namespace json {
55
56struct serialization_opts {
57 explicit serialization_opts()
58 : allow_non_string_keys(false),
59 javascript_safe(false),
60 pretty_formatting(false),
61 encode_non_ascii(false),
62 validate_utf8(false),
63 allow_trailing_comma(false),
64 sort_keys(false),
65 skip_invalid_utf8(false),
66 allow_nan_inf(false),
67 double_mode(double_conversion::DoubleToStringConverter::SHORTEST),
68 double_num_digits(0), // ignored when mode is SHORTEST
69 double_fallback(false),
70 parse_numbers_as_strings(false),
71 recursion_limit(100),
72 extra_ascii_to_escape_bitmap{{0, 0}} {}
73
74 // If true, keys in an object can be non-strings. (In strict
75 // JSON, object keys must be strings.) This is used by dynamic's
76 // operator<<.
77 bool allow_non_string_keys;
78
79 /*
80 * If true, refuse to serialize 64-bit numbers that cannot be
81 * precisely represented by fit a double---instead, throws an
82 * exception if the document contains this.
83 */
84 bool javascript_safe;
85
86 // If true, the serialized json will contain space and newlines to
87 // try to be minimally "pretty".
88 bool pretty_formatting;
89
90 // If true, non-ASCII utf8 characters would be encoded as \uXXXX:
91 // - if the code point is in [U+0000..U+FFFF] => encode as a single \uXXXX
92 // - if the code point is > U+FFFF => encode as 2 UTF-16 surrogate pairs.
93 bool encode_non_ascii;
94
95 // Check that strings are valid utf8
96 bool validate_utf8;
97
98 // Allow trailing comma in lists of values / items
99 bool allow_trailing_comma;
100
101 // Sort keys of all objects before printing out (potentially slow)
102 // using dynamic::operator<.
103 // Has no effect if sort_keys_by is set.
104 bool sort_keys;
105
106 // Sort keys of all objects before printing out (potentially slow)
107 // using the provided less functor.
108 Function<bool(dynamic const&, dynamic const&) const> sort_keys_by;
109
110 // Replace invalid utf8 characters with U+FFFD and continue
111 bool skip_invalid_utf8;
112
113 // true to allow NaN or INF values
114 bool allow_nan_inf;
115
116 // Options for how to print floating point values. See Conv.h
117 // toAppend implementation for floating point for more info
118 double_conversion::DoubleToStringConverter::DtoaMode double_mode;
119 unsigned int double_num_digits;
120
121 // Fallback to double when a value that looks like integer is too big to
122 // fit in an int64_t. Can result in loss a of precision.
123 bool double_fallback;
124
125 // Do not parse numbers. Instead, store them as strings and leave the
126 // conversion up to the user.
127 bool parse_numbers_as_strings;
128
129 // Recursion limit when parsing.
130 unsigned int recursion_limit;
131
132 // Bitmap representing ASCII characters to escape with unicode
133 // representations. The least significant bit of the first in the pair is
134 // ASCII value 0; the most significant bit of the second in the pair is ASCII
135 // value 127. Some specific characters in this range are always escaped
136 // regardless of the bitmask - namely characters less than 0x20, \, and ".
137 std::array<uint64_t, 2> extra_ascii_to_escape_bitmap;
138};
139
140/*
141 * Generates a bitmap with bits set for each of the ASCII characters provided
142 * for use in the serialization_opts extra_ascii_to_escape_bitmap option. If any
143 * characters are not valid ASCII, they are ignored.
144 */
145std::array<uint64_t, 2> buildExtraAsciiToEscapeBitmap(StringPiece chars);
146
147/*
148 * Main JSON serialization routine taking folly::dynamic parameters.
149 * For the most common use cases there are simpler functions in the
150 * main folly namespace below.
151 */
152std::string serialize(dynamic const&, serialization_opts const&);
153
154/*
155 * Escape a string so that it is legal to print it in JSON text and
156 * append the result to out.
157 */
158
159void escapeString(
160 StringPiece input,
161 std::string& out,
162 const serialization_opts& opts);
163
164/*
165 * Strip all C99-like comments (i.e. // and / * ... * /)
166 */
167std::string stripComments(StringPiece jsonC);
168
169} // namespace json
170
171//////////////////////////////////////////////////////////////////////
172
173/*
174 * Parse a json blob out of a range and produce a dynamic representing
175 * it.
176 */
177dynamic parseJson(StringPiece, json::serialization_opts const&);
178dynamic parseJson(StringPiece);
179
180/*
181 * Serialize a dynamic into a json string.
182 */
183std::string toJson(dynamic const&);
184
185/*
186 * Same as the above, except format the json with some minimal
187 * indentation.
188 */
189std::string toPrettyJson(dynamic const&);
190
191/*
192 * Printer for GTest.
193 * Uppercase name to fill GTest's API, which calls this method through ADL.
194 */
195void PrintTo(const dynamic&, std::ostream*);
196//////////////////////////////////////////////////////////////////////
197
198} // namespace folly
199