| // Reading a message JSON with Reader (SAX-style API). | |
| // The JSON should be an object with key-string pairs. | |
| #include "rapidjson/reader.h" | |
| #include "rapidjson/error/en.h" | |
| #include <iostream> | |
| #include <string> | |
| #include <map> | |
| using namespace std; | |
| using namespace rapidjson; | |
| typedef map<string, string> MessageMap; | |
| #if defined(__GNUC__) | |
| RAPIDJSON_DIAG_PUSH | |
| RAPIDJSON_DIAG_OFF(effc++) | |
| #endif | |
| #ifdef __clang__ | |
| RAPIDJSON_DIAG_PUSH | |
| RAPIDJSON_DIAG_OFF(switch-enum) | |
| #endif | |
| struct MessageHandler | |
| : public BaseReaderHandler<UTF8<>, MessageHandler> { | |
| MessageHandler() : messages_(), state_(kExpectObjectStart), name_() {} | |
| bool StartObject() { | |
| switch (state_) { | |
| case kExpectObjectStart: | |
| state_ = kExpectNameOrObjectEnd; | |
| return true; | |
| default: | |
| return false; | |
| } | |
| } | |
| bool String(const char* str, SizeType length, bool) { | |
| switch (state_) { | |
| case kExpectNameOrObjectEnd: | |
| name_ = string(str, length); | |
| state_ = kExpectValue; | |
| return true; | |
| case kExpectValue: | |
| messages_.insert(MessageMap::value_type(name_, string(str, length))); | |
| state_ = kExpectNameOrObjectEnd; | |
| return true; | |
| default: | |
| return false; | |
| } | |
| } | |
| bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; } | |
| bool Default() { return false; } // All other events are invalid. | |
| MessageMap messages_; | |
| enum State { | |
| kExpectObjectStart, | |
| kExpectNameOrObjectEnd, | |
| kExpectValue | |
| }state_; | |
| std::string name_; | |
| }; | |
| #if defined(__GNUC__) | |
| RAPIDJSON_DIAG_POP | |
| #endif | |
| #ifdef __clang__ | |
| RAPIDJSON_DIAG_POP | |
| #endif | |
| static void ParseMessages(const char* json, MessageMap& messages) { | |
| Reader reader; | |
| MessageHandler handler; | |
| StringStream ss(json); | |
| if (reader.Parse(ss, handler)) | |
| messages.swap(handler.messages_); // Only change it if success. | |
| else { | |
| ParseErrorCode e = reader.GetParseErrorCode(); | |
| size_t o = reader.GetErrorOffset(); | |
| cout << "Error: " << GetParseError_En(e) << endl;; | |
| cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl; | |
| } | |
| } | |
| int main() { | |
| MessageMap messages; | |
| const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }"; | |
| cout << json1 << endl; | |
| ParseMessages(json1, messages); | |
| for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr) | |
| cout << itr->first << ": " << itr->second << endl; | |
| cout << endl << "Parse a JSON with invalid schema." << endl; | |
| const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }"; | |
| cout << json2 << endl; | |
| ParseMessages(json2, messages); | |
| return 0; | |
| } |