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