filterkeydom.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // JSON filterkey example which populates filtered SAX events into a Document.
  2. // This example parses JSON text from stdin with validation.
  3. // During parsing, specified key will be filtered using a SAX handler.
  4. // And finally the filtered events are used to populate a Document.
  5. // As an example, the document is written to standard output.
  6. #include <rtthread.h>
  7. #include "rapidjson/document.h"
  8. #include "rapidjson/writer.h"
  9. #include "rapidjson/filereadstream.h"
  10. #include "rapidjson/filewritestream.h"
  11. #include "rapidjson/error/en.h"
  12. #include <stack>
  13. using namespace rapidjson;
  14. // This handler forwards event into an output handler, with filtering the descendent events of specified key.
  15. template <typename OutputHandler>
  16. class FilterKeyHandler {
  17. public:
  18. typedef char Ch;
  19. FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) :
  20. outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_()
  21. {}
  22. bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); }
  23. bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); }
  24. bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); }
  25. bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); }
  26. bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); }
  27. bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); }
  28. bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); }
  29. bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); }
  30. bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); }
  31. bool StartObject() {
  32. if (filterValueDepth_ > 0) {
  33. filterValueDepth_++;
  34. return true;
  35. }
  36. else {
  37. filteredKeyCount_.push(0);
  38. return outputHandler_.StartObject();
  39. }
  40. }
  41. bool Key(const Ch* str, SizeType len, bool copy) {
  42. if (filterValueDepth_ > 0)
  43. return true;
  44. else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) {
  45. filterValueDepth_ = 1;
  46. return true;
  47. }
  48. else {
  49. ++filteredKeyCount_.top();
  50. return outputHandler_.Key(str, len, copy);
  51. }
  52. }
  53. bool EndObject(SizeType) {
  54. if (filterValueDepth_ > 0) {
  55. filterValueDepth_--;
  56. return EndValue();
  57. }
  58. else {
  59. // Use our own filtered memberCount
  60. SizeType memberCount = filteredKeyCount_.top();
  61. filteredKeyCount_.pop();
  62. return outputHandler_.EndObject(memberCount) && EndValue();
  63. }
  64. }
  65. bool StartArray() {
  66. if (filterValueDepth_ > 0) {
  67. filterValueDepth_++;
  68. return true;
  69. }
  70. else
  71. return outputHandler_.StartArray();
  72. }
  73. bool EndArray(SizeType elementCount) {
  74. if (filterValueDepth_ > 0) {
  75. filterValueDepth_--;
  76. return EndValue();
  77. }
  78. else
  79. return outputHandler_.EndArray(elementCount) && EndValue();
  80. }
  81. private:
  82. FilterKeyHandler(const FilterKeyHandler&);
  83. FilterKeyHandler& operator=(const FilterKeyHandler&);
  84. bool EndValue() {
  85. if (filterValueDepth_ == 1) // Just at the end of value after filtered key
  86. filterValueDepth_ = 0;
  87. return true;
  88. }
  89. OutputHandler& outputHandler_;
  90. const char* keyString_;
  91. const SizeType keyLength_;
  92. unsigned filterValueDepth_;
  93. std::stack<SizeType> filteredKeyCount_;
  94. };
  95. // Implements a generator for Document::Populate()
  96. template <typename InputStream>
  97. class FilterKeyReader {
  98. public:
  99. typedef char Ch;
  100. FilterKeyReader(InputStream& is, const Ch* keyString, SizeType keyLength) :
  101. is_(is), keyString_(keyString), keyLength_(keyLength), parseResult_()
  102. {}
  103. // SAX event flow: reader -> filter -> handler
  104. template <typename Handler>
  105. bool operator()(Handler& handler) {
  106. FilterKeyHandler<Handler> filter(handler, keyString_, keyLength_);
  107. Reader reader;
  108. parseResult_ = reader.Parse(is_, filter);
  109. return parseResult_;
  110. }
  111. const ParseResult& GetParseResult() const { return parseResult_; }
  112. private:
  113. FilterKeyReader(const FilterKeyReader&);
  114. FilterKeyReader& operator=(const FilterKeyReader&);
  115. InputStream& is_;
  116. const char* keyString_;
  117. const SizeType keyLength_;
  118. ParseResult parseResult_;
  119. };
  120. int filter_key_dom(int argc, char* argv[]) {
  121. if (argc != 2) {
  122. fprintf(stderr, "filterkeydom key < input.json > output.json\n");
  123. return 1;
  124. }
  125. // Prepare input stream.
  126. char readBuffer[1024];
  127. FileReadStream is(stdin, readBuffer, sizeof(readBuffer));
  128. // Prepare Filter
  129. FilterKeyReader<FileReadStream> reader(is, argv[1], static_cast<SizeType>(strlen(argv[1])));
  130. // Populates the filtered events from reader
  131. Document document;
  132. document.Populate(reader);
  133. ParseResult pr = reader.GetParseResult();
  134. if (!pr) {
  135. fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(pr.Offset()), GetParseError_En(pr.Code()));
  136. return 1;
  137. }
  138. // Prepare JSON writer and output stream.
  139. char writeBuffer[1024];
  140. FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
  141. Writer<FileWriteStream> writer(os);
  142. // Write the document to standard output
  143. document.Accept(writer);
  144. return 0;
  145. }
  146. MSH_CMD_EXPORT(filter_key_dom, rapid json filter key dom example);