json_writer.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #include "json_writer.h"
  2. #include <library/cpp/json/json_writer.h>
  3. namespace NYT {
  4. ////////////////////////////////////////////////////////////////////////////////
  5. static bool IsSpecialJsonKey(const TStringBuf& key) {
  6. return key.size() > 0 && key[0] == '$';
  7. }
  8. ////////////////////////////////////////////////////////////////////////////////
  9. TJsonWriter::TJsonWriter(
  10. IOutputStream* output,
  11. ::NYson::EYsonType type,
  12. EJsonFormat format,
  13. EJsonAttributesMode attributesMode,
  14. ESerializedBoolFormat booleanFormat)
  15. : TJsonWriter(
  16. output,
  17. NJson::TJsonWriterConfig{}.SetFormatOutput(format == JF_PRETTY),
  18. type,
  19. attributesMode,
  20. booleanFormat
  21. )
  22. {}
  23. TJsonWriter::TJsonWriter(
  24. IOutputStream* output,
  25. NJson::TJsonWriterConfig config,
  26. ::NYson::EYsonType type,
  27. EJsonAttributesMode attributesMode,
  28. ESerializedBoolFormat booleanFormat)
  29. : Output(output)
  30. , Type(type)
  31. , AttributesMode(attributesMode)
  32. , BooleanFormat(booleanFormat)
  33. , Depth(0)
  34. {
  35. if (Type == ::NYson::EYsonType::MapFragment) {
  36. ythrow ::NYson::TYsonException() << ("Map fragments are not supported by Json");
  37. }
  38. UnderlyingJsonWriter.Reset(new NJson::TJsonWriter(
  39. output,
  40. config));
  41. JsonWriter = UnderlyingJsonWriter.Get();
  42. HasAttributes = false;
  43. InAttributesBalance = 0;
  44. }
  45. void TJsonWriter::EnterNode() {
  46. if (AttributesMode == JAM_NEVER) {
  47. HasAttributes = false;
  48. } else if (AttributesMode == JAM_ON_DEMAND) {
  49. // Do nothing
  50. } else if (AttributesMode == JAM_ALWAYS) {
  51. if (!HasAttributes) {
  52. JsonWriter->OpenMap();
  53. JsonWriter->Write("$attributes");
  54. JsonWriter->OpenMap();
  55. JsonWriter->CloseMap();
  56. }
  57. HasAttributes = true;
  58. }
  59. HasUnfoldedStructureStack.push_back(HasAttributes);
  60. if (HasAttributes) {
  61. JsonWriter->Write("$value");
  62. HasAttributes = false;
  63. }
  64. Depth += 1;
  65. }
  66. void TJsonWriter::LeaveNode() {
  67. Y_ASSERT(!HasUnfoldedStructureStack.empty());
  68. if (HasUnfoldedStructureStack.back()) {
  69. // Close map of the {$attributes, $value}
  70. JsonWriter->CloseMap();
  71. }
  72. HasUnfoldedStructureStack.pop_back();
  73. Depth -= 1;
  74. if (Depth == 0 && Type == ::NYson::EYsonType::ListFragment && InAttributesBalance == 0) {
  75. JsonWriter->Flush();
  76. Output->Write("\n");
  77. }
  78. }
  79. bool TJsonWriter::IsWriteAllowed() {
  80. if (AttributesMode == JAM_NEVER) {
  81. return InAttributesBalance == 0;
  82. }
  83. return true;
  84. }
  85. void TJsonWriter::OnStringScalar(TStringBuf value) {
  86. if (IsWriteAllowed()) {
  87. EnterNode();
  88. WriteStringScalar(value);
  89. LeaveNode();
  90. }
  91. }
  92. void TJsonWriter::OnInt64Scalar(i64 value) {
  93. if (IsWriteAllowed()) {
  94. EnterNode();
  95. JsonWriter->Write(value);
  96. LeaveNode();
  97. }
  98. }
  99. void TJsonWriter::OnUint64Scalar(ui64 value) {
  100. if (IsWriteAllowed()) {
  101. EnterNode();
  102. JsonWriter->Write(value);
  103. LeaveNode();
  104. }
  105. }
  106. void TJsonWriter::OnDoubleScalar(double value) {
  107. if (IsWriteAllowed()) {
  108. EnterNode();
  109. JsonWriter->Write(value);
  110. LeaveNode();
  111. }
  112. }
  113. void TJsonWriter::OnBooleanScalar(bool value) {
  114. if (IsWriteAllowed()) {
  115. if (BooleanFormat == SBF_STRING) {
  116. OnStringScalar(value ? "true" : "false");
  117. } else {
  118. EnterNode();
  119. JsonWriter->Write(value);
  120. LeaveNode();
  121. }
  122. }
  123. }
  124. void TJsonWriter::OnEntity() {
  125. if (IsWriteAllowed()) {
  126. EnterNode();
  127. JsonWriter->WriteNull();
  128. LeaveNode();
  129. }
  130. }
  131. void TJsonWriter::OnBeginList() {
  132. if (IsWriteAllowed()) {
  133. EnterNode();
  134. JsonWriter->OpenArray();
  135. }
  136. }
  137. void TJsonWriter::OnListItem() {
  138. }
  139. void TJsonWriter::OnEndList() {
  140. if (IsWriteAllowed()) {
  141. JsonWriter->CloseArray();
  142. LeaveNode();
  143. }
  144. }
  145. void TJsonWriter::OnBeginMap() {
  146. if (IsWriteAllowed()) {
  147. EnterNode();
  148. JsonWriter->OpenMap();
  149. }
  150. }
  151. void TJsonWriter::OnKeyedItem(TStringBuf name) {
  152. if (IsWriteAllowed()) {
  153. if (IsSpecialJsonKey(name)) {
  154. WriteStringScalar(TString("$") + name);
  155. } else {
  156. WriteStringScalar(name);
  157. }
  158. }
  159. }
  160. void TJsonWriter::OnEndMap() {
  161. if (IsWriteAllowed()) {
  162. JsonWriter->CloseMap();
  163. LeaveNode();
  164. }
  165. }
  166. void TJsonWriter::OnBeginAttributes() {
  167. InAttributesBalance += 1;
  168. if (AttributesMode != JAM_NEVER) {
  169. JsonWriter->OpenMap();
  170. JsonWriter->Write("$attributes");
  171. JsonWriter->OpenMap();
  172. }
  173. }
  174. void TJsonWriter::OnEndAttributes() {
  175. InAttributesBalance -= 1;
  176. if (AttributesMode != JAM_NEVER) {
  177. HasAttributes = true;
  178. JsonWriter->CloseMap();
  179. }
  180. }
  181. void TJsonWriter::WriteStringScalar(const TStringBuf& value) {
  182. JsonWriter->Write(value);
  183. }
  184. void TJsonWriter::Flush() {
  185. JsonWriter->Flush();
  186. }
  187. ////////////////////////////////////////////////////////////////////////////////
  188. }