/src/jsoncpp/include/json/writer.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors |
2 | | // Distributed under MIT license, or public domain if desired and |
3 | | // recognized in your jurisdiction. |
4 | | // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE |
5 | | |
6 | | #ifndef JSON_WRITER_H_INCLUDED |
7 | | #define JSON_WRITER_H_INCLUDED |
8 | | |
9 | | #if !defined(JSON_IS_AMALGAMATION) |
10 | | #include "value.h" |
11 | | #endif // if !defined(JSON_IS_AMALGAMATION) |
12 | | #include <ostream> |
13 | | #include <string> |
14 | | #include <vector> |
15 | | |
16 | | // Disable warning C4251: <data member>: <type> needs to have dll-interface to |
17 | | // be used by... |
18 | | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER) |
19 | | #pragma warning(push) |
20 | | #pragma warning(disable : 4251) |
21 | | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) |
22 | | |
23 | | #pragma pack(push) |
24 | | #pragma pack() |
25 | | |
26 | | namespace Json { |
27 | | |
28 | | class Value; |
29 | | |
30 | | /** |
31 | | * |
32 | | * Usage: |
33 | | * \code |
34 | | * using namespace Json; |
35 | | * void writeToStdout(StreamWriter::Factory const& factory, Value const& value) |
36 | | * { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter()); |
37 | | * writer->write(value, &std::cout); |
38 | | * std::cout << std::endl; // add lf and flush |
39 | | * } |
40 | | * \endcode |
41 | | */ |
42 | | class JSON_API StreamWriter { |
43 | | protected: |
44 | | OStream* sout_; // not owned; will not delete |
45 | | public: |
46 | | StreamWriter(); |
47 | | virtual ~StreamWriter(); |
48 | | /** Write Value into document as configured in sub-class. |
49 | | * Do not take ownership of sout, but maintain a reference during function. |
50 | | * \pre sout != NULL |
51 | | * \return zero on success (For now, we always return zero, so check the |
52 | | * stream instead.) \throw std::exception possibly, depending on |
53 | | * configuration |
54 | | */ |
55 | | virtual int write(Value const& root, OStream* sout) = 0; |
56 | | |
57 | | /** \brief A simple abstract factory. |
58 | | */ |
59 | | class JSON_API Factory { |
60 | | public: |
61 | | virtual ~Factory(); |
62 | | /** \brief Allocate a CharReader via operator new(). |
63 | | * \throw std::exception if something goes wrong (e.g. invalid settings) |
64 | | */ |
65 | | virtual StreamWriter* newStreamWriter() const = 0; |
66 | | }; // Factory |
67 | | }; // StreamWriter |
68 | | |
69 | | /** \brief Write into stringstream, then return string, for convenience. |
70 | | * A StreamWriter will be created from the factory, used, and then deleted. |
71 | | */ |
72 | | String JSON_API writeString(StreamWriter::Factory const& factory, |
73 | | Value const& root); |
74 | | |
75 | | /** \brief Build a StreamWriter implementation. |
76 | | |
77 | | * Usage: |
78 | | * \code |
79 | | * using namespace Json; |
80 | | * Value value = ...; |
81 | | * StreamWriterBuilder builder; |
82 | | * builder["commentStyle"] = "None"; |
83 | | * builder["indentation"] = " "; // or whatever you like |
84 | | * std::unique_ptr<Json::StreamWriter> writer( |
85 | | * builder.newStreamWriter()); |
86 | | * writer->write(value, &std::cout); |
87 | | * std::cout << std::endl; // add lf and flush |
88 | | * \endcode |
89 | | */ |
90 | | class JSON_API StreamWriterBuilder : public StreamWriter::Factory { |
91 | | public: |
92 | | // Note: We use a Json::Value so that we can add data-members to this class |
93 | | // without a major version bump. |
94 | | /** Configuration of this builder. |
95 | | * Available settings (case-sensitive): |
96 | | * - "commentStyle": "None" or "All" |
97 | | * - "indentation": "<anything>". |
98 | | * - Setting this to an empty string also omits newline characters. |
99 | | * - "enableYAMLCompatibility": false or true |
100 | | * - slightly change the whitespace around colons |
101 | | * - "dropNullPlaceholders": false or true |
102 | | * - Drop the "null" string from the writer's output for nullValues. |
103 | | * Strictly speaking, this is not valid JSON. But when the output is being |
104 | | * fed to a browser's JavaScript, it makes for smaller output and the |
105 | | * browser can handle the output just fine. |
106 | | * - "useSpecialFloats": false or true |
107 | | * - If true, outputs non-finite floating point values in the following way: |
108 | | * NaN values as "NaN", positive infinity as "Infinity", and negative |
109 | | * infinity as "-Infinity". |
110 | | * - "precision": int |
111 | | * - Number of precision digits for formatting of real values. |
112 | | * - "precisionType": "significant"(default) or "decimal" |
113 | | * - Type of precision for formatting of real values. |
114 | | * - "emitUTF8": false or true |
115 | | * - If true, outputs raw UTF8 strings instead of escaping them. |
116 | | |
117 | | * You can examine 'settings_` yourself |
118 | | * to see the defaults. You can also write and read them just like any |
119 | | * JSON Value. |
120 | | * \sa setDefaults() |
121 | | */ |
122 | | Json::Value settings_; |
123 | | |
124 | | StreamWriterBuilder(); |
125 | | ~StreamWriterBuilder() override; |
126 | | |
127 | | /** |
128 | | * \throw std::exception if something goes wrong (e.g. invalid settings) |
129 | | */ |
130 | | StreamWriter* newStreamWriter() const override; |
131 | | |
132 | | /** \return true if 'settings' are legal and consistent; |
133 | | * otherwise, indicate bad settings via 'invalid'. |
134 | | */ |
135 | | bool validate(Json::Value* invalid) const; |
136 | | /** A simple way to update a specific setting. |
137 | | */ |
138 | | Value& operator[](const String& key); |
139 | | |
140 | | /** Called by ctor, but you can use this to reset settings_. |
141 | | * \pre 'settings' != NULL (but Json::null is fine) |
142 | | * \remark Defaults: |
143 | | * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults |
144 | | */ |
145 | | static void setDefaults(Json::Value* settings); |
146 | | }; |
147 | | |
148 | | /** \brief Abstract class for writers. |
149 | | * \deprecated Use StreamWriter. (And really, this is an implementation detail.) |
150 | | */ |
151 | | class JSON_API Writer { |
152 | | public: |
153 | | virtual ~Writer(); |
154 | | |
155 | | virtual String write(const Value& root) = 0; |
156 | | }; |
157 | | |
158 | | /** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format |
159 | | *without formatting (not human friendly). |
160 | | * |
161 | | * The JSON document is written in a single line. It is not intended for 'human' |
162 | | *consumption, |
163 | | * but may be useful to support feature such as RPC where bandwidth is limited. |
164 | | * \sa Reader, Value |
165 | | * \deprecated Use StreamWriterBuilder. |
166 | | */ |
167 | | #if defined(_MSC_VER) |
168 | | #pragma warning(push) |
169 | | #pragma warning(disable : 4996) // Deriving from deprecated class |
170 | | #endif |
171 | | class JSON_API FastWriter : public Writer { |
172 | | public: |
173 | | FastWriter(); |
174 | 0 | ~FastWriter() override = default; |
175 | | |
176 | | void enableYAMLCompatibility(); |
177 | | |
178 | | /** \brief Drop the "null" string from the writer's output for nullValues. |
179 | | * Strictly speaking, this is not valid JSON. But when the output is being |
180 | | * fed to a browser's JavaScript, it makes for smaller output and the |
181 | | * browser can handle the output just fine. |
182 | | */ |
183 | | void dropNullPlaceholders(); |
184 | | |
185 | | void omitEndingLineFeed(); |
186 | | |
187 | | public: // overridden from Writer |
188 | | String write(const Value& root) override; |
189 | | |
190 | | private: |
191 | | void writeValue(const Value& value); |
192 | | |
193 | | String document_; |
194 | | bool yamlCompatibilityEnabled_{false}; |
195 | | bool dropNullPlaceholders_{false}; |
196 | | bool omitEndingLineFeed_{false}; |
197 | | }; |
198 | | #if defined(_MSC_VER) |
199 | | #pragma warning(pop) |
200 | | #endif |
201 | | |
202 | | /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a |
203 | | *human friendly way. |
204 | | * |
205 | | * The rules for line break and indent are as follow: |
206 | | * - Object value: |
207 | | * - if empty then print {} without indent and line break |
208 | | * - if not empty the print '{', line break & indent, print one value per |
209 | | *line |
210 | | * and then unindent and line break and print '}'. |
211 | | * - Array value: |
212 | | * - if empty then print [] without indent and line break |
213 | | * - if the array contains no object value, empty array or some other value |
214 | | *types, |
215 | | * and all the values fit on one lines, then print the array on a single |
216 | | *line. |
217 | | * - otherwise, it the values do not fit on one line, or the array contains |
218 | | * object or non empty array, then print one value per line. |
219 | | * |
220 | | * If the Value have comments then they are outputted according to their |
221 | | *#CommentPlacement. |
222 | | * |
223 | | * \sa Reader, Value, Value::setComment() |
224 | | * \deprecated Use StreamWriterBuilder. |
225 | | */ |
226 | | #if defined(_MSC_VER) |
227 | | #pragma warning(push) |
228 | | #pragma warning(disable : 4996) // Deriving from deprecated class |
229 | | #endif |
230 | | class JSON_API StyledWriter : public Writer { |
231 | | public: |
232 | | StyledWriter(); |
233 | 0 | ~StyledWriter() override = default; |
234 | | |
235 | | public: // overridden from Writer |
236 | | /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. |
237 | | * \param root Value to serialize. |
238 | | * \return String containing the JSON document that represents the root value. |
239 | | */ |
240 | | String write(const Value& root) override; |
241 | | |
242 | | private: |
243 | | void writeValue(const Value& value); |
244 | | void writeArrayValue(const Value& value); |
245 | | bool isMultilineArray(const Value& value); |
246 | | void pushValue(const String& value); |
247 | | void writeIndent(); |
248 | | void writeWithIndent(const String& value); |
249 | | void indent(); |
250 | | void unindent(); |
251 | | void writeCommentBeforeValue(const Value& root); |
252 | | void writeCommentAfterValueOnSameLine(const Value& root); |
253 | | static bool hasCommentForValue(const Value& value); |
254 | | static String normalizeEOL(const String& text); |
255 | | |
256 | | using ChildValues = std::vector<String>; |
257 | | |
258 | | ChildValues childValues_; |
259 | | String document_; |
260 | | String indentString_; |
261 | | unsigned int rightMargin_{74}; |
262 | | unsigned int indentSize_{3}; |
263 | | bool addChildValues_{false}; |
264 | | }; |
265 | | #if defined(_MSC_VER) |
266 | | #pragma warning(pop) |
267 | | #endif |
268 | | |
269 | | /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a |
270 | | human friendly way, |
271 | | to a stream rather than to a string. |
272 | | * |
273 | | * The rules for line break and indent are as follow: |
274 | | * - Object value: |
275 | | * - if empty then print {} without indent and line break |
276 | | * - if not empty the print '{', line break & indent, print one value per |
277 | | line |
278 | | * and then unindent and line break and print '}'. |
279 | | * - Array value: |
280 | | * - if empty then print [] without indent and line break |
281 | | * - if the array contains no object value, empty array or some other value |
282 | | types, |
283 | | * and all the values fit on one lines, then print the array on a single |
284 | | line. |
285 | | * - otherwise, it the values do not fit on one line, or the array contains |
286 | | * object or non empty array, then print one value per line. |
287 | | * |
288 | | * If the Value have comments then they are outputted according to their |
289 | | #CommentPlacement. |
290 | | * |
291 | | * \sa Reader, Value, Value::setComment() |
292 | | * \deprecated Use StreamWriterBuilder. |
293 | | */ |
294 | | #if defined(_MSC_VER) |
295 | | #pragma warning(push) |
296 | | #pragma warning(disable : 4996) // Deriving from deprecated class |
297 | | #endif |
298 | | class JSON_API StyledStreamWriter { |
299 | | public: |
300 | | /** |
301 | | * \param indentation Each level will be indented by this amount extra. |
302 | | */ |
303 | | StyledStreamWriter(String indentation = "\t"); |
304 | | ~StyledStreamWriter() = default; |
305 | | |
306 | | public: |
307 | | /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format. |
308 | | * \param out Stream to write to. (Can be ostringstream, e.g.) |
309 | | * \param root Value to serialize. |
310 | | * \note There is no point in deriving from Writer, since write() should not |
311 | | * return a value. |
312 | | */ |
313 | | void write(OStream& out, const Value& root); |
314 | | |
315 | | private: |
316 | | void writeValue(const Value& value); |
317 | | void writeArrayValue(const Value& value); |
318 | | bool isMultilineArray(const Value& value); |
319 | | void pushValue(const String& value); |
320 | | void writeIndent(); |
321 | | void writeWithIndent(const String& value); |
322 | | void indent(); |
323 | | void unindent(); |
324 | | void writeCommentBeforeValue(const Value& root); |
325 | | void writeCommentAfterValueOnSameLine(const Value& root); |
326 | | static bool hasCommentForValue(const Value& value); |
327 | | static String normalizeEOL(const String& text); |
328 | | |
329 | | using ChildValues = std::vector<String>; |
330 | | |
331 | | ChildValues childValues_; |
332 | | OStream* document_; |
333 | | String indentString_; |
334 | | unsigned int rightMargin_{74}; |
335 | | String indentation_; |
336 | | bool addChildValues_ : 1; |
337 | | bool indented_ : 1; |
338 | | }; |
339 | | #if defined(_MSC_VER) |
340 | | #pragma warning(pop) |
341 | | #endif |
342 | | |
343 | | #if defined(JSON_HAS_INT64) |
344 | | String JSON_API valueToString(Int value); |
345 | | String JSON_API valueToString(UInt value); |
346 | | #endif // if defined(JSON_HAS_INT64) |
347 | | String JSON_API valueToString(LargestInt value); |
348 | | String JSON_API valueToString(LargestUInt value); |
349 | | String JSON_API valueToString( |
350 | | double value, unsigned int precision = Value::defaultRealPrecision, |
351 | | PrecisionType precisionType = PrecisionType::significantDigits); |
352 | | String JSON_API valueToString(bool value); |
353 | | String JSON_API valueToQuotedString(const char* value); |
354 | | String JSON_API valueToQuotedString(const char* value, size_t length); |
355 | | |
356 | | /// \brief Output using the StyledStreamWriter. |
357 | | /// \see Json::operator>>() |
358 | | JSON_API OStream& operator<<(OStream&, const Value& root); |
359 | | |
360 | | } // namespace Json |
361 | | |
362 | | #pragma pack(pop) |
363 | | |
364 | | #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) |
365 | | #pragma warning(pop) |
366 | | #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) |
367 | | |
368 | | #endif // JSON_WRITER_H_INCLUDED |