writer.h 12 KB

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