Commit 05b2ed75 authored by Milo Yip's avatar Milo Yip

Add filterkey and filterkeydom examples

parent 96ca8479
......@@ -7,6 +7,8 @@ endif()
set(EXAMPLES
capitalize
condense
filterkey
filterkeydom
jsonx
messagereader
parsebyparts
......
// 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>
struct FilterKeyHandler {
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();
}
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;
}
// 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>
struct FilterKeyHandler {
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();
}
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)
{}
// SAX event flow: reader -> filter -> handler
template <typename Handler>
bool operator()(Handler& handler) {
FilterKeyHandler<Handler> filter(handler, keyString_, keyLength_);
Reader reader;
return parseResult_ = reader.Parse(is_, filter);
}
const ParseResult& GetParseResult() const { return parseResult_; }
private:
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;
}
......@@ -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`.
......@@ -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`
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment