writer.h 12 KB

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