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