json_easy_parser.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "json_easy_parser.h"
  2. #include <library/cpp/json/json_reader.h>
  3. #include <util/string/cast.h>
  4. #include <util/string/split.h>
  5. #include <util/string/strip.h>
  6. namespace NJson {
  7. static TString MAP_IDENTIFIER = "{}";
  8. static TString ARRAY_IDENTIFIER = "[]";
  9. static TString ANY_IDENTIFIER = "*";
  10. static void ParsePath(TString path, TVector<TPathElem>* res) {
  11. TVector<const char*> parts;
  12. Split(path.begin(), '/', &parts);
  13. for (size_t n = 0; n < parts.size(); ++n) {
  14. TString part = Strip(parts[n]);
  15. if (!part.empty()) {
  16. if (part[0] != '[') {
  17. res->push_back(TPathElem(NImpl::MAP));
  18. res->push_back(TPathElem(part));
  19. } else {
  20. int arrayCounter;
  21. try {
  22. arrayCounter = FromString<int>(part.substr(1, part.length() - 2));
  23. } catch (yexception&) {
  24. arrayCounter = -1;
  25. }
  26. res->push_back(TPathElem(arrayCounter));
  27. }
  28. }
  29. }
  30. }
  31. void TJsonParser::AddField(const TString& path, bool nonEmpty) {
  32. Fields.emplace_back();
  33. Fields.back().NonEmpty = nonEmpty;
  34. ParsePath(path, &Fields.back().Path);
  35. }
  36. TString TJsonParser::ConvertToTabDelimited(const TString& json) const {
  37. TStringInput in(json);
  38. TStringStream out;
  39. ConvertToTabDelimited(in, out);
  40. return out.Str();
  41. }
  42. class TRewriteJsonImpl: public NJson::TJsonCallbacks {
  43. const TJsonParser& Parent;
  44. TVector<TString> FieldValues;
  45. TVector<TPathElem> Stack;
  46. bool ShouldUpdateOnArrayChange;
  47. int CurrentFieldIdx;
  48. bool HasFormatError;
  49. private:
  50. static bool PathElementMatch(const TPathElem& templ, const TPathElem& real) {
  51. if (templ.Type != real.Type)
  52. return false;
  53. if (templ.Type == NImpl::ARRAY)
  54. return templ.ArrayCounter == -1 || templ.ArrayCounter == real.ArrayCounter;
  55. if (templ.Type == NImpl::MAP_KEY)
  56. return templ.Key == ANY_IDENTIFIER || templ.Key == real.Key;
  57. return true;
  58. }
  59. bool CheckFilter(const TVector<TPathElem>& path) const {
  60. if (Stack.size() < path.size())
  61. return false;
  62. for (size_t n = 0; n < path.size(); ++n) {
  63. if (!PathElementMatch(path[n], Stack[n]))
  64. return false;
  65. }
  66. return true;
  67. }
  68. void UpdateRule() {
  69. for (size_t n = 0; n < Parent.Fields.size(); ++n) {
  70. if (FieldValues[n].empty() && CheckFilter(Parent.Fields[n].Path)) {
  71. CurrentFieldIdx = n;
  72. return;
  73. }
  74. }
  75. CurrentFieldIdx = -1;
  76. }
  77. void Pop() {
  78. Stack.pop_back();
  79. }
  80. void IncreaseArrayCounter() {
  81. if (!Stack.empty() && Stack.back().Type == NImpl::ARRAY) {
  82. ++Stack.back().ArrayCounter;
  83. if (ShouldUpdateOnArrayChange)
  84. UpdateRule();
  85. }
  86. }
  87. template <class T>
  88. bool OnValue(const T& val) {
  89. IncreaseArrayCounter();
  90. if (CurrentFieldIdx >= 0) {
  91. FieldValues[CurrentFieldIdx] = ToString(val);
  92. UpdateRule();
  93. }
  94. return true;
  95. }
  96. public:
  97. TRewriteJsonImpl(const TJsonParser& parent)
  98. : Parent(parent)
  99. , FieldValues(parent.Fields.size())
  100. , ShouldUpdateOnArrayChange(false)
  101. , CurrentFieldIdx(-1)
  102. , HasFormatError(false)
  103. {
  104. for (size_t n = 0; n < Parent.Fields.size(); ++n) {
  105. if (!Parent.Fields[n].Path.empty() && Parent.Fields[n].Path.back().Type == NImpl::ARRAY)
  106. ShouldUpdateOnArrayChange = true;
  107. }
  108. }
  109. bool OnOpenMap() override {
  110. IncreaseArrayCounter();
  111. Stack.push_back(TPathElem(NImpl::MAP));
  112. if (CurrentFieldIdx >= 0)
  113. HasFormatError = true;
  114. else
  115. UpdateRule();
  116. return true;
  117. }
  118. bool OnOpenArray() override {
  119. IncreaseArrayCounter();
  120. Stack.push_back(TPathElem(-1));
  121. if (CurrentFieldIdx >= 0)
  122. HasFormatError = true;
  123. else
  124. UpdateRule();
  125. return true;
  126. }
  127. bool OnCloseMap() override {
  128. while (!Stack.empty() && Stack.back().Type != NImpl::MAP)
  129. Pop();
  130. if (!Stack.empty())
  131. Pop();
  132. UpdateRule();
  133. return true;
  134. }
  135. bool OnCloseArray() override {
  136. if (!Stack.empty())
  137. Pop();
  138. UpdateRule();
  139. return true;
  140. }
  141. bool OnMapKey(const TStringBuf& key) override {
  142. if (!Stack.empty() && Stack.back().Type == NImpl::MAP_KEY) {
  143. Pop();
  144. UpdateRule();
  145. }
  146. Stack.push_back(TPathElem(TString{key}));
  147. if (CurrentFieldIdx >= 0)
  148. HasFormatError = true;
  149. else
  150. UpdateRule();
  151. return true;
  152. }
  153. bool OnBoolean(bool b) override {
  154. return OnValue(b);
  155. }
  156. bool OnInteger(long long i) override {
  157. return OnValue(i);
  158. }
  159. bool OnDouble(double f) override {
  160. return OnValue(f);
  161. }
  162. bool OnString(const TStringBuf& str) override {
  163. return OnValue(str);
  164. }
  165. bool IsOK() const {
  166. if (HasFormatError)
  167. return false;
  168. for (size_t n = 0; n < FieldValues.size(); ++n)
  169. if (Parent.Fields[n].NonEmpty && FieldValues[n].empty())
  170. return false;
  171. return true;
  172. }
  173. void WriteTo(IOutputStream& out) const {
  174. for (size_t n = 0; n < FieldValues.size(); ++n)
  175. out << "\t" << FieldValues[n];
  176. }
  177. void WriteTo(TVector<TString>* res) const {
  178. *res = FieldValues;
  179. }
  180. };
  181. void TJsonParser::ConvertToTabDelimited(IInputStream& in, IOutputStream& out) const {
  182. TRewriteJsonImpl impl(*this);
  183. ReadJson(&in, &impl);
  184. if (impl.IsOK()) {
  185. out << Prefix;
  186. impl.WriteTo(out);
  187. out.Flush();
  188. }
  189. }
  190. bool TJsonParser::Parse(const TString& json, TVector<TString>* res) const {
  191. TRewriteJsonImpl impl(*this);
  192. TStringInput in(json);
  193. ReadJson(&in, &impl);
  194. if (impl.IsOK()) {
  195. impl.WriteTo(res);
  196. return true;
  197. } else
  198. return false;
  199. }
  200. //struct TTestMe {
  201. // TTestMe() {
  202. // TJsonParser worker;
  203. // worker.AddField("/x/y/z", true);
  204. // TString ret1 = worker.ConvertToTabDelimited("{ \"x\" : { \"y\" : { \"w\" : 1, \"z\" : 2 } } }");
  205. // TString ret2 = worker.ConvertToTabDelimited(" [1, 2, 3, 4, 5] ");
  206. // }
  207. //} testMe;
  208. }