1 // Reading a message JSON with Reader (SAX-style API).
2 // The JSON should be an object with key-string pairs.
3
4 #include "rapidjson/reader.h"
5 #include "rapidjson/error/en.h"
6 #include <iostream>
7 #include <string>
8 #include <map>
9
10 using namespace std;
11 using namespace rapidjson;
12
13 typedef map<string, string> MessageMap;
14
15 #if defined(__GNUC__)
16 RAPIDJSON_DIAG_PUSH
17 RAPIDJSON_DIAG_OFF(effc++)
18 #endif
19
20 struct MessageHandler
21 : public BaseReaderHandler<UTF8<>, MessageHandler> {
MessageHandlerMessageHandler22 MessageHandler() : messages_(), state_(kExpectObjectStart), name_() {}
23
StartObjectMessageHandler24 bool StartObject() {
25 switch (state_) {
26 case kExpectObjectStart:
27 state_ = kExpectNameOrObjectEnd;
28 return true;
29 default:
30 return false;
31 }
32 }
33
StringMessageHandler34 bool String(const char* str, SizeType length, bool) {
35 switch (state_) {
36 case kExpectNameOrObjectEnd:
37 name_ = string(str, length);
38 state_ = kExpectValue;
39 return true;
40 case kExpectValue:
41 messages_.insert(MessageMap::value_type(name_, string(str, length)));
42 state_ = kExpectNameOrObjectEnd;
43 return true;
44 default:
45 return false;
46 }
47 }
48
EndObjectMessageHandler49 bool EndObject(SizeType) { return state_ == kExpectNameOrObjectEnd; }
50
DefaultMessageHandler51 bool Default() { return false; } // All other events are invalid.
52
53 MessageMap messages_;
54 enum State {
55 kExpectObjectStart,
56 kExpectNameOrObjectEnd,
57 kExpectValue
58 }state_;
59 std::string name_;
60 };
61
62 #if defined(__GNUC__)
63 RAPIDJSON_DIAG_POP
64 #endif
65
ParseMessages(const char * json,MessageMap & messages)66 void ParseMessages(const char* json, MessageMap& messages) {
67 Reader reader;
68 MessageHandler handler;
69 StringStream ss(json);
70 if (reader.Parse(ss, handler))
71 messages.swap(handler.messages_); // Only change it if success.
72 else {
73 ParseErrorCode e = reader.GetParseErrorCode();
74 size_t o = reader.GetErrorOffset();
75 cout << "Error: " << GetParseError_En(e) << endl;;
76 cout << " at offset " << o << " near '" << string(json).substr(o, 10) << "...'" << endl;
77 }
78 }
79
main()80 int main() {
81 MessageMap messages;
82
83 const char* json1 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\" }";
84 cout << json1 << endl;
85 ParseMessages(json1, messages);
86
87 for (MessageMap::const_iterator itr = messages.begin(); itr != messages.end(); ++itr)
88 cout << itr->first << ": " << itr->second << endl;
89
90 cout << endl << "Parse a JSON with invalid schema." << endl;
91 const char* json2 = "{ \"greeting\" : \"Hello!\", \"farewell\" : \"bye-bye!\", \"foo\" : {} }";
92 cout << json2 << endl;
93 ParseMessages(json2, messages);
94
95 return 0;
96 }
97