filterkeydom.cpp 5.8 KB

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