Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filterkey and filterkeydom examples #615

Merged
merged 4 commits into from
Apr 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ endif()
set(EXAMPLES
capitalize
condense
filterkey
filterkeydom
jsonx
messagereader
parsebyparts
Expand Down
135 changes: 135 additions & 0 deletions example/filterkey/filterkey.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
// JSON filterkey example with SAX-style API.

// This example parses JSON text from stdin with validation.
// During parsing, specified key will be filtered using a SAX handler.
// It re-output the JSON content to stdout without whitespace.

#include "rapidjson/reader.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
#include <stack>

using namespace rapidjson;

// This handler forwards event into an output handler, with filtering the descendent events of specified key.
template <typename OutputHandler>
class FilterKeyHandler {
public:
typedef char Ch;

FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) :
outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_()
{}

bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); }
bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); }
bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); }
bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); }
bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); }
bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); }
bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); }
bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); }
bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); }

bool StartObject() {
if (filterValueDepth_ > 0) {
filterValueDepth_++;
return true;
}
else {
filteredKeyCount_.push(0);
return outputHandler_.StartObject();
}
}

bool Key(const Ch* str, SizeType len, bool copy) {
if (filterValueDepth_ > 0)
return true;
else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) {
filterValueDepth_ = 1;
return true;
}
else {
++filteredKeyCount_.top();
return outputHandler_.Key(str, len, copy);
}
}

bool EndObject(SizeType) {
if (filterValueDepth_ > 0) {
filterValueDepth_--;
return EndValue();
}
else {
// Use our own filtered memberCount
SizeType memberCount = filteredKeyCount_.top();
filteredKeyCount_.pop();
return outputHandler_.EndObject(memberCount) && EndValue();
}
}

bool StartArray() {
if (filterValueDepth_ > 0) {
filterValueDepth_++;
return true;
}
else
return outputHandler_.StartArray();
}

bool EndArray(SizeType elementCount) {
if (filterValueDepth_ > 0) {
filterValueDepth_--;
return EndValue();
}
else
return outputHandler_.EndArray(elementCount) && EndValue();
}

private:
FilterKeyHandler(const FilterKeyHandler&);
FilterKeyHandler& operator=(const FilterKeyHandler&);

bool EndValue() {
if (filterValueDepth_ == 1) // Just at the end of value after filtered key
filterValueDepth_ = 0;
return true;
}

OutputHandler& outputHandler_;
const char* keyString_;
const SizeType keyLength_;
unsigned filterValueDepth_;
std::stack<SizeType> filteredKeyCount_;
};

int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "filterkey key < input.json > output.json\n");
return 1;
}

// Prepare JSON reader and input stream.
Reader reader;
char readBuffer[65536];
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));

// Prepare JSON writer and output stream.
char writeBuffer[65536];
FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
Writer<FileWriteStream> writer(os);

// Prepare Filter
FilterKeyHandler<Writer<FileWriteStream> > filter(writer, argv[1], static_cast<SizeType>(strlen(argv[1])));

// JSON reader parse from the input stream, filter handler filters the events, and forward to writer.
// i.e. the events flow is: reader -> filter -> writer
if (!reader.Parse(is, filter)) {
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(reader.GetErrorOffset()), GetParseError_En(reader.GetParseErrorCode()));
return 1;
}

return 0;
}
170 changes: 170 additions & 0 deletions example/filterkeydom/filterkeydom.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// JSON filterkey example which populates filtered SAX events into a Document.

// This example parses JSON text from stdin with validation.
// During parsing, specified key will be filtered using a SAX handler.
// And finally the filtered events are used to populate a Document.
// As an example, the document is written to standard output.

#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "rapidjson/filewritestream.h"
#include "rapidjson/error/en.h"
#include <stack>

using namespace rapidjson;

// This handler forwards event into an output handler, with filtering the descendent events of specified key.
template <typename OutputHandler>
class FilterKeyHandler {
public:
typedef char Ch;

FilterKeyHandler(OutputHandler& outputHandler, const Ch* keyString, SizeType keyLength) :
outputHandler_(outputHandler), keyString_(keyString), keyLength_(keyLength), filterValueDepth_(), filteredKeyCount_()
{}

bool Null() { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Null() && EndValue(); }
bool Bool(bool b) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Bool(b) && EndValue(); }
bool Int(int i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int(i) && EndValue(); }
bool Uint(unsigned u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint(u) && EndValue(); }
bool Int64(int64_t i) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Int64(i) && EndValue(); }
bool Uint64(uint64_t u) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Uint64(u) && EndValue(); }
bool Double(double d) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.Double(d) && EndValue(); }
bool RawNumber(const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.RawNumber(str, len, copy) && EndValue(); }
bool String (const Ch* str, SizeType len, bool copy) { return filterValueDepth_ > 0 ? EndValue() : outputHandler_.String (str, len, copy) && EndValue(); }

bool StartObject() {
if (filterValueDepth_ > 0) {
filterValueDepth_++;
return true;
}
else {
filteredKeyCount_.push(0);
return outputHandler_.StartObject();
}
}

bool Key(const Ch* str, SizeType len, bool copy) {
if (filterValueDepth_ > 0)
return true;
else if (len == keyLength_ && std::memcmp(str, keyString_, len) == 0) {
filterValueDepth_ = 1;
return true;
}
else {
++filteredKeyCount_.top();
return outputHandler_.Key(str, len, copy);
}
}

bool EndObject(SizeType) {
if (filterValueDepth_ > 0) {
filterValueDepth_--;
return EndValue();
}
else {
// Use our own filtered memberCount
SizeType memberCount = filteredKeyCount_.top();
filteredKeyCount_.pop();
return outputHandler_.EndObject(memberCount) && EndValue();
}
}

bool StartArray() {
if (filterValueDepth_ > 0) {
filterValueDepth_++;
return true;
}
else
return outputHandler_.StartArray();
}

bool EndArray(SizeType elementCount) {
if (filterValueDepth_ > 0) {
filterValueDepth_--;
return EndValue();
}
else
return outputHandler_.EndArray(elementCount) && EndValue();
}

private:
FilterKeyHandler(const FilterKeyHandler&);
FilterKeyHandler& operator=(const FilterKeyHandler&);

bool EndValue() {
if (filterValueDepth_ == 1) // Just at the end of value after filtered key
filterValueDepth_ = 0;
return true;
}

OutputHandler& outputHandler_;
const char* keyString_;
const SizeType keyLength_;
unsigned filterValueDepth_;
std::stack<SizeType> filteredKeyCount_;
};

// Implements a generator for Document::Populate()
template <typename InputStream>
class FilterKeyReader {
public:
typedef char Ch;

FilterKeyReader(InputStream& is, const Ch* keyString, SizeType keyLength) :
is_(is), keyString_(keyString), keyLength_(keyLength), parseResult_()
{}

// SAX event flow: reader -> filter -> handler
template <typename Handler>
bool operator()(Handler& handler) {
FilterKeyHandler<Handler> filter(handler, keyString_, keyLength_);
Reader reader;
parseResult_ = reader.Parse(is_, filter);
return parseResult_;
}

const ParseResult& GetParseResult() const { return parseResult_; }

private:
FilterKeyReader(const FilterKeyReader&);
FilterKeyReader& operator=(const FilterKeyReader&);

InputStream& is_;
const char* keyString_;
const SizeType keyLength_;
ParseResult parseResult_;
};

int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "filterkeydom key < input.json > output.json\n");
return 1;
}

// Prepare input stream.
char readBuffer[65536];
FileReadStream is(stdin, readBuffer, sizeof(readBuffer));

// Prepare Filter
FilterKeyReader<FileReadStream> reader(is, argv[1], static_cast<SizeType>(strlen(argv[1])));

// Populates the filtered events from reader
Document document;
document.Populate(reader);
ParseResult pr = reader.GetParseResult();
if (!pr) {
fprintf(stderr, "\nError(%u): %s\n", static_cast<unsigned>(pr.Offset()), GetParseError_En(pr.Code()));
return 1;
}

// Prepare JSON writer and output stream.
char writeBuffer[65536];
FileWriteStream os(stdout, writeBuffer, sizeof(writeBuffer));
Writer<FileWriteStream> writer(os);

// Write the document to standard output
document.Accept(writer);
return 0;
}
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,5 @@ More [examples](https://github.com/miloyip/rapidjson/tree/master/example) are av
* Advanced
* [prettyauto](https://github.com/miloyip/rapidjson/blob/master/example/prettyauto/prettyauto.cpp): A modified version of [pretty](https://github.com/miloyip/rapidjson/blob/master/example/pretty/pretty.cpp) to automatically handle JSON with any UTF encodings.
* [parsebyparts](https://github.com/miloyip/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): Implements an `AsyncDocumentParser` which can parse JSON in parts, using C++11 thread.
* [filterkey](https://github.com/miloyip/rapidjson/blob/master/example/filterkey/filterkey.cpp): A command line tool to remove all values with user-specified key.
* [filterkeydom](https://github.com/miloyip/rapidjson/blob/master/example/filterkey/filterkey.cpp): Same tool as above, but it demonstrates how to use a generator to populate a `Document`.
2 changes: 2 additions & 0 deletions readme.zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,5 @@ int main() {
* 进阶
* [prettyauto](https://github.com/miloyip/rapidjson/blob/master/example/prettyauto/prettyauto.cpp): [pretty](https://github.com/miloyip/rapidjson/blob/master/example/pretty/pretty.cpp) 的修改版本,可自动处理任何 UTF 编码的 JSON。
* [parsebyparts](https://github.com/miloyip/rapidjson/blob/master/example/parsebyparts/parsebyparts.cpp): 这例子中的 `AsyncDocumentParser` 类使用 C++ 线程来逐段解析 JSON。
* [filterkey](https://github.com/miloyip/rapidjson/blob/master/example/filterkey/filterkey.cpp): 移取使用者指定的键值的命令行工具。
* [filterkeydom](https://github.com/miloyip/rapidjson/blob/master/example/filterkey/filterkey.cpp): 如上的工具,但展示如何使用生成器(generator)去填充一个 `Document`。