Coverage Report

Created: 2025-07-09 06:07

/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