| // 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; |
| } |