json.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #pragma once
  2. #include <util/generic/noncopyable.h>
  3. #include <util/generic/ptr.h>
  4. #include <util/generic/string.h>
  5. #include <util/generic/vector.h>
  6. #include <util/generic/yexception.h>
  7. #include <util/stream/str.h>
  8. #include <util/string/cast.h>
  9. namespace NJson {
  10. class TJsonValue;
  11. }
  12. namespace NJsonWriter {
  13. enum EJsonEntity : ui8 {
  14. JE_OUTER_SPACE = 1,
  15. JE_LIST,
  16. JE_OBJECT,
  17. JE_PAIR,
  18. };
  19. enum EHtmlEscapeMode {
  20. HEM_ESCAPE_HTML = 1, // Use HTML escaping: &lt; &gt; &amp; \/
  21. HEM_DONT_ESCAPE_HTML, // Use JSON escaping: \u003C \u003E \u0026 \/
  22. HEM_RELAXED, // Use JSON escaping: \u003C \u003E \u0026 /
  23. HEM_UNSAFE, // Turn escaping off: < > & /
  24. };
  25. class TError: public yexception {};
  26. class TValueContext;
  27. class TPairContext;
  28. class TAfterColonContext;
  29. struct TBufState {
  30. bool NeedComma;
  31. bool NeedNewline;
  32. TVector<EJsonEntity> Stack;
  33. };
  34. class TBuf : TNonCopyable {
  35. public:
  36. TBuf(EHtmlEscapeMode mode = HEM_DONT_ESCAPE_HTML, IOutputStream* stream = nullptr);
  37. TValueContext WriteString(const TStringBuf& s, EHtmlEscapeMode hem);
  38. TValueContext WriteString(const TStringBuf& s);
  39. TValueContext WriteInt(int i);
  40. TValueContext WriteLongLong(long long i);
  41. TValueContext WriteULongLong(unsigned long long i);
  42. TValueContext WriteFloat(float f, EFloatToStringMode mode = PREC_NDIGITS, int ndigits = 6);
  43. TValueContext WriteDouble(double f, EFloatToStringMode mode = PREC_NDIGITS, int ndigits = 10);
  44. TValueContext WriteBool(bool b);
  45. TValueContext WriteNull();
  46. TValueContext WriteJsonValue(const NJson::TJsonValue* value, bool sortKeys = false, EFloatToStringMode mode = PREC_NDIGITS, int ndigits = 10);
  47. TValueContext BeginList();
  48. TBuf& EndList();
  49. TPairContext BeginObject();
  50. TAfterColonContext WriteKey(const TStringBuf& key, EHtmlEscapeMode hem);
  51. TAfterColonContext WriteKey(const TStringBuf& key);
  52. TAfterColonContext UnsafeWriteKey(const TStringBuf& key);
  53. bool KeyExpected() const {
  54. return Stack.back() == JE_OBJECT;
  55. }
  56. //! deprecated, do not use in new code
  57. TAfterColonContext CompatWriteKeyWithoutQuotes(const TStringBuf& key);
  58. TBuf& EndObject();
  59. /*** Indent the resulting JSON with spaces.
  60. * By default (spaces==0) no formatting is done. */
  61. TBuf& SetIndentSpaces(int spaces) {
  62. IndentSpaces = spaces;
  63. return *this;
  64. }
  65. /*** NaN and Inf are not valid json values,
  66. * so if WriteNanAsString is set, writer would write string
  67. * intead of throwing exception (default case) */
  68. TBuf& SetWriteNanAsString(bool writeNanAsString = true) {
  69. WriteNanAsString = writeNanAsString;
  70. return *this;
  71. }
  72. /*** Return the string formed in the internal TStringStream.
  73. * You may only call it if the `stream' parameter was NULL
  74. * at construction time. */
  75. const TString& Str() const;
  76. /*** Dump and forget the string constructed so far.
  77. * You may only call it if the `stream' parameter was NULL
  78. * at construction time. */
  79. void FlushTo(IOutputStream* stream);
  80. /*** Write a literal string that represents a JSON value
  81. * (string, number, object, array, bool, or null).
  82. *
  83. * Example:
  84. * j.UnsafeWriteValue("[1, 2, 3, \"o'clock\", 4, \"o'clock rock\"]");
  85. *
  86. * As in all of the Unsafe* functions, no escaping is done. */
  87. void UnsafeWriteValue(const TStringBuf& s);
  88. void UnsafeWriteValue(const char* s, size_t len);
  89. /*** When in the context of an object, write a literal string
  90. * that represents a key:value pair (or several pairs).
  91. *
  92. * Example:
  93. * j.BeginObject();
  94. * j.UnsafeWritePair("\"adam\": \"male\", \"eve\": \"female\"");
  95. * j.EndObject();
  96. *
  97. * As in all of the Unsafe* functions, no escaping is done. */
  98. TPairContext UnsafeWritePair(const TStringBuf& s);
  99. /*** Copy the supplied string directly into the output stream. */
  100. void UnsafeWriteRawBytes(const TStringBuf& s);
  101. void UnsafeWriteRawBytes(const char* c, size_t len);
  102. TBufState State() const;
  103. void Reset(const TBufState& from);
  104. void Reset(TBufState&& from);
  105. private:
  106. void BeginValue();
  107. void EndValue();
  108. void BeginKey();
  109. void RawWriteChar(char c);
  110. bool EscapedWriteChar(const char* b, const char* c, EHtmlEscapeMode hem);
  111. void WriteBareString(const TStringBuf s, EHtmlEscapeMode hem);
  112. void WriteComma();
  113. void PrintIndentation(bool closing);
  114. void PrintWhitespaces(size_t count, bool prependWithNewLine);
  115. void WriteHexEscape(unsigned char c);
  116. void StackPush(EJsonEntity e);
  117. void StackPop();
  118. void CheckAndPop(EJsonEntity e);
  119. EJsonEntity StackTop() const;
  120. template <class TFloat>
  121. TValueContext WriteFloatImpl(TFloat f, EFloatToStringMode mode, int ndigits);
  122. private:
  123. IOutputStream* Stream;
  124. THolder<TStringStream> StringStream;
  125. typedef TVector<const TString*> TKeys;
  126. TKeys Keys;
  127. TVector<EJsonEntity> Stack;
  128. bool NeedComma;
  129. bool NeedNewline;
  130. const EHtmlEscapeMode EscapeMode;
  131. int IndentSpaces;
  132. bool WriteNanAsString;
  133. };
  134. // Please don't try to instantiate the classes declared below this point.
  135. template <typename TOutContext>
  136. class TValueWriter {
  137. public:
  138. TOutContext WriteNull();
  139. TOutContext WriteString(const TStringBuf&);
  140. TOutContext WriteString(const TStringBuf& s, EHtmlEscapeMode hem);
  141. TOutContext WriteInt(int);
  142. TOutContext WriteLongLong(long long);
  143. TOutContext WriteULongLong(unsigned long long);
  144. TOutContext WriteBool(bool);
  145. TOutContext WriteFloat(float);
  146. TOutContext WriteFloat(float, EFloatToStringMode, int ndigits);
  147. TOutContext WriteDouble(double);
  148. TOutContext WriteDouble(double, EFloatToStringMode, int ndigits);
  149. TOutContext WriteJsonValue(const NJson::TJsonValue* value, bool sortKeys = false);
  150. TOutContext UnsafeWriteValue(const TStringBuf&);
  151. TValueContext BeginList();
  152. TPairContext BeginObject();
  153. protected:
  154. TValueWriter(TBuf& buf)
  155. : Buf(buf)
  156. {
  157. }
  158. friend class TBuf;
  159. protected:
  160. TBuf& Buf;
  161. };
  162. class TValueContext: public TValueWriter<TValueContext> {
  163. public:
  164. TBuf& EndList() {
  165. return Buf.EndList();
  166. }
  167. TString Str() const {
  168. return Buf.Str();
  169. }
  170. private:
  171. TValueContext(TBuf& buf)
  172. : TValueWriter<TValueContext>(buf)
  173. {
  174. }
  175. friend class TBuf;
  176. friend class TValueWriter<TValueContext>;
  177. };
  178. class TAfterColonContext: public TValueWriter<TPairContext> {
  179. private:
  180. TAfterColonContext(TBuf& iBuf)
  181. : TValueWriter<TPairContext>(iBuf)
  182. {
  183. }
  184. friend class TBuf;
  185. friend class TPairContext;
  186. };
  187. class TPairContext {
  188. public:
  189. TAfterColonContext WriteKey(const TStringBuf& s, EHtmlEscapeMode hem) {
  190. return Buf.WriteKey(s, hem);
  191. }
  192. TAfterColonContext WriteKey(const TStringBuf& s) {
  193. return Buf.WriteKey(s);
  194. }
  195. TAfterColonContext UnsafeWriteKey(const TStringBuf& s) {
  196. return Buf.UnsafeWriteKey(s);
  197. }
  198. TAfterColonContext CompatWriteKeyWithoutQuotes(const TStringBuf& s) {
  199. return Buf.CompatWriteKeyWithoutQuotes(s);
  200. }
  201. TPairContext UnsafeWritePair(const TStringBuf& s) {
  202. return Buf.UnsafeWritePair(s);
  203. }
  204. TBuf& EndObject() {
  205. return Buf.EndObject();
  206. }
  207. private:
  208. TPairContext(TBuf& buf)
  209. : Buf(buf)
  210. {
  211. }
  212. friend class TBuf;
  213. friend class TValueWriter<TPairContext>;
  214. private:
  215. TBuf& Buf;
  216. };
  217. #define JSON_VALUE_WRITER_WRAP(function, params, args) \
  218. template <typename TOutContext> \
  219. TOutContext TValueWriter<TOutContext>::function params { \
  220. Buf.function args; \
  221. return TOutContext(Buf); \
  222. }
  223. JSON_VALUE_WRITER_WRAP(WriteNull, (), ())
  224. JSON_VALUE_WRITER_WRAP(WriteString, (const TStringBuf& arg), (arg))
  225. JSON_VALUE_WRITER_WRAP(WriteString, (const TStringBuf& s, EHtmlEscapeMode hem), (s, hem))
  226. JSON_VALUE_WRITER_WRAP(WriteInt, (int arg), (arg))
  227. JSON_VALUE_WRITER_WRAP(WriteLongLong, (long long arg), (arg))
  228. JSON_VALUE_WRITER_WRAP(WriteULongLong, (unsigned long long arg), (arg))
  229. JSON_VALUE_WRITER_WRAP(WriteBool, (bool arg), (arg))
  230. JSON_VALUE_WRITER_WRAP(WriteFloat, (float arg), (arg))
  231. JSON_VALUE_WRITER_WRAP(WriteFloat, (float arg, EFloatToStringMode mode, int ndigits), (arg, mode, ndigits))
  232. JSON_VALUE_WRITER_WRAP(WriteDouble, (double arg), (arg))
  233. JSON_VALUE_WRITER_WRAP(WriteDouble, (double arg, EFloatToStringMode mode, int ndigits), (arg, mode, ndigits))
  234. JSON_VALUE_WRITER_WRAP(WriteJsonValue, (const NJson::TJsonValue* value, bool sortKeys), (value, sortKeys))
  235. JSON_VALUE_WRITER_WRAP(UnsafeWriteValue, (const TStringBuf& arg), (arg))
  236. #undef JSON_VALUE_WRITER_WRAP
  237. template <typename TOutContext>
  238. TValueContext TValueWriter<TOutContext>::BeginList() {
  239. return Buf.BeginList();
  240. }
  241. template <typename TOutContext>
  242. TPairContext TValueWriter<TOutContext>::BeginObject() {
  243. return Buf.BeginObject();
  244. }
  245. TString WrapJsonToCallback(const TBuf& buf, TStringBuf callback);
  246. }