106 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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;
 | |
| }
 |