mirror of
https://github.com/Tencent/rapidjson.git
synced 2025-03-06 13:41:35 +01:00
Merge pull request #615 from miloyip/example
Add filterkey and filterkeydom examples
This commit is contained in:
commit
fdf665d637
@ -7,6 +7,8 @@ endif()
|
||||
set(EXAMPLES
|
||||
capitalize
|
||||
condense
|
||||
filterkey
|
||||
filterkeydom
|
||||
jsonx
|
||||
messagereader
|
||||
parsebyparts
|
||||
|
135
example/filterkey/filterkey.cpp
Normal file
135
example/filterkey/filterkey.cpp
Normal file
@ -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
example/filterkeydom/filterkeydom.cpp
Normal file
170
example/filterkeydom/filterkeydom.cpp
Normal file
@ -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;
|
||||
}
|
@ -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`。
|
Loading…
x
Reference in New Issue
Block a user