Skip to content

Commit 55bf37c

Browse files
committed
Encapsulate RapidJSON dependency and use SAX readers/writers
1 parent aa252df commit 55bf37c

File tree

4 files changed

+205
-249
lines changed

4 files changed

+205
-249
lines changed

JSONResponse.cpp

Lines changed: 168 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -3,182 +3,245 @@
33

44
#include <graphqlservice/JSONResponse.h>
55

6+
#define RAPIDJSON_NAMESPACE facebook::graphql::rapidjson
7+
#define RAPIDJSON_NAMESPACE_BEGIN namespace facebook { namespace graphql { namespace rapidjson {
8+
#define RAPIDJSON_NAMESPACE_END } /* namespace rapidjson */ } /* namespace graphql */ } /* namespace facebook */
9+
#include <rapidjson/rapidjson.h>
10+
11+
#include <rapidjson/stringbuffer.h>
12+
#include <rapidjson/writer.h>
13+
#include <rapidjson/reader.h>
14+
15+
#include <stack>
16+
617
namespace facebook {
718
namespace graphql {
8-
namespace rapidjson {
19+
namespace response {
920

10-
Value convertResponse(Document::AllocatorType& allocator, response::Value&& response)
21+
void writeResponse(rapidjson::Writer<rapidjson::StringBuffer>& writer, Value&& response)
1122
{
1223
switch (response.type())
1324
{
14-
case response::Type::Map:
25+
case Type::Map:
1526
{
16-
Value result(Type::kObjectType);
17-
auto members = response.release<response::MapType>();
27+
auto members = response.release<MapType>();
28+
29+
writer.StartObject();
1830

1931
for (auto& entry : members)
2032
{
21-
result.AddMember(
22-
Value(entry.first.c_str(), static_cast<SizeType>(entry.first.size()), allocator),
23-
convertResponse(allocator, std::move(entry.second)), allocator);
33+
writer.Key(entry.first.c_str());
34+
writeResponse(writer, std::move(entry.second));
2435
}
2536

26-
return result;
37+
writer.EndObject();
38+
break;
2739
}
2840

29-
case response::Type::List:
41+
case Type::List:
3042
{
31-
Value result(Type::kArrayType);
32-
auto elements = response.release<response::ListType>();
43+
auto elements = response.release<ListType>();
44+
45+
writer.StartArray();
3346

34-
result.Reserve(static_cast<SizeType>(elements.size()), allocator);
3547
for (auto& entry : elements)
3648
{
37-
result.PushBack(convertResponse(allocator, std::move(entry)), allocator);
49+
writeResponse(writer, std::move(entry));
3850
}
3951

40-
return result;
52+
writer.EndArray();
53+
break;
4154
}
4255

43-
case response::Type::String:
44-
case response::Type::EnumValue:
56+
case Type::String:
57+
case Type::EnumValue:
4558
{
46-
Value result(Type::kStringType);
47-
auto value = response.release<response::StringType>();
59+
auto value = response.release<StringType>();
4860

49-
result.SetString(value.c_str(), static_cast<SizeType>(value.size()), allocator);
50-
51-
return result;
61+
writer.String(value.c_str());
62+
break;
5263
}
5364

54-
case response::Type::Null:
65+
case Type::Null:
5566
{
56-
Value result(Type::kNullType);
57-
58-
return result;
67+
writer.Null();
68+
break;
5969
}
6070

61-
case response::Type::Boolean:
71+
case Type::Boolean:
6272
{
63-
Value result(response.get<response::BooleanType>()
64-
? Type::kTrueType
65-
: Type::kFalseType);
66-
67-
return result;
73+
writer.Bool(response.get<BooleanType>());
74+
break;
6875
}
6976

70-
case response::Type::Int:
77+
case Type::Int:
7178
{
72-
Value result(Type::kNumberType);
73-
74-
result.SetInt(response.get<response::IntType>());
75-
76-
return result;
79+
writer.Int(response.get<IntType>());
80+
break;
7781
}
7882

79-
case response::Type::Float:
83+
case Type::Float:
8084
{
81-
Value result(Type::kNumberType);
82-
83-
result.SetDouble(response.get<response::FloatType>());
84-
85-
return result;
85+
writer.Double(response.get<FloatType>());
86+
break;
8687
}
8788

88-
case response::Type::Scalar:
89+
case Type::Scalar:
8990
{
90-
return convertResponse(allocator, response.release<response::ScalarType>());
91+
writeResponse(writer, response.release<ScalarType>());
92+
break;
9193
}
9294

9395
default:
9496
{
95-
return Value(Type::kNullType);
97+
writer.Null();
98+
break;
9699
}
97100
}
98101
}
99102

100-
Document convertResponse(response::Value&& response)
103+
std::string toJSON(Value&& response)
101104
{
102-
Document document;
103-
auto result = convertResponse(document.GetAllocator(), std::move(response));
105+
rapidjson::StringBuffer buffer;
106+
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
104107

105-
static_cast<Value&>(document).Swap(result);
106-
107-
return document;
108+
writeResponse(writer, std::move(response));
109+
return buffer.GetString();
108110
}
109111

110-
111-
response::Value convertResponse(const Value& value)
112+
struct ResponseHandler
113+
: rapidjson::BaseReaderHandler<rapidjson::UTF8<>, ResponseHandler>
112114
{
113-
switch (value.GetType())
115+
ResponseHandler()
114116
{
115-
case Type::kNullType:
116-
return response::Value();
117+
// Start with a single null value.
118+
_responseStack.push({});
119+
}
117120

118-
case Type::kFalseType:
119-
return response::Value(false);
121+
Value getResponse()
122+
{
123+
auto response = std::move(_responseStack.top());
120124

121-
case Type::kTrueType:
122-
return response::Value(true);
125+
_responseStack.pop();
123126

124-
case Type::kObjectType:
125-
{
126-
response::Value response(response::Type::Map);
127+
return response;
128+
}
127129

128-
response.reserve(static_cast<size_t>(value.MemberCount()));
129-
for (const auto& member : value.GetObject())
130-
{
131-
response.emplace_back(member.name.GetString(),
132-
convertResponse(member.value));
133-
}
130+
bool Null()
131+
{
132+
setValue(Value());
133+
return true;
134+
}
134135

135-
return response;
136-
}
136+
bool Bool(bool b)
137+
{
138+
setValue(Value(b));
139+
return true;
140+
}
137141

138-
case Type::kArrayType:
139-
{
140-
response::Value response(response::Type::List);
142+
bool Int(int i)
143+
{
144+
auto value = Value(Type::Int);
141145

142-
response.reserve(static_cast<size_t>(value.Size()));
143-
for (const auto& element : value.GetArray())
144-
{
145-
response.emplace_back(convertResponse(element));
146-
}
146+
value.set<IntType>(std::move(i));
147+
setValue(std::move(value));
148+
return true;
149+
}
147150

148-
return response;
149-
}
151+
bool Uint(unsigned int i)
152+
{
153+
return Int(static_cast<int>(i));
154+
}
150155

151-
case Type::kStringType:
152-
return response::Value(std::string(value.GetString()));
156+
bool Int64(int64_t i)
157+
{
158+
return Int(static_cast<int>(i));
159+
}
153160

154-
case Type::kNumberType:
161+
bool Uint64(uint64_t i)
162+
{
163+
return Int(static_cast<int>(i));
164+
}
165+
166+
bool Double(double d)
167+
{
168+
auto value = Value(Type::Float);
169+
170+
value.set<FloatType>(std::move(d));
171+
setValue(std::move(value));
172+
return true;
173+
}
174+
175+
bool String(const Ch* str, rapidjson::SizeType /*length*/, bool /*copy*/)
176+
{
177+
setValue(Value(std::string(str)));
178+
return true;
179+
}
180+
181+
bool StartObject()
182+
{
183+
_responseStack.push(Value(Type::Map));
184+
return true;
185+
}
186+
187+
bool Key(const Ch* str, rapidjson::SizeType /*length*/, bool /*copy*/)
188+
{
189+
_key = str;
190+
return true;
191+
}
192+
193+
bool EndObject(rapidjson::SizeType /*count*/)
194+
{
195+
setValue(getResponse());
196+
return true;
197+
}
198+
199+
bool StartArray()
200+
{
201+
_responseStack.push(Value(Type::List));
202+
return true;
203+
}
204+
205+
bool EndArray(rapidjson::SizeType /*count*/)
206+
{
207+
setValue(getResponse());
208+
return true;
209+
}
210+
211+
private:
212+
void setValue(Value&& value)
213+
{
214+
switch (_responseStack.top().type())
155215
{
156-
response::Value response(value.IsInt()
157-
? response::Type::Int
158-
: response::Type::Float);
216+
case Type::Map:
217+
_responseStack.top().emplace_back(std::move(_key), std::move(value));
218+
break;
159219

160-
if (value.IsInt())
161-
{
162-
response.set<response::IntType>(value.GetInt());
163-
}
164-
else
165-
{
166-
response.set<response::FloatType>(value.GetDouble());
167-
}
220+
case Type::List:
221+
_responseStack.top().emplace_back(std::move(value));
222+
break;
168223

169-
return response;
224+
default:
225+
_responseStack.top() = std::move(value);
226+
break;
170227
}
171-
172-
default:
173-
return response::Value();
174228
}
175-
}
176229

177-
response::Value convertResponse(const Document& document)
230+
std::string _key;
231+
std::stack<Value> _responseStack;
232+
};
233+
234+
Value parseJSON(const std::string& json)
178235
{
179-
return convertResponse(static_cast<const Value&>(document));
236+
ResponseHandler handler;
237+
rapidjson::Reader reader;
238+
rapidjson::StringStream ss(json.c_str());
239+
240+
reader.Parse(ss, handler);
241+
242+
return handler.getResponse();
180243
}
181244

182-
} /* namespace rapidjson */
245+
} /* namespace response */
183246
} /* namespace graphql */
184247
} /* namespace facebook */

include/graphqlservice/JSONResponse.h

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,14 @@
55

66
#include <graphqlservice/GraphQLResponse.h>
77

8-
#define RAPIDJSON_NAMESPACE facebook::graphql::rapidjson
9-
#define RAPIDJSON_NAMESPACE_BEGIN namespace facebook { namespace graphql { namespace rapidjson {
10-
#define RAPIDJSON_NAMESPACE_END } /* namespace rapidjson */ } /* namespace graphql */ } /* namespace facebook */
11-
#include <rapidjson/document.h>
12-
138
namespace facebook {
149
namespace graphql {
15-
namespace rapidjson {
10+
namespace response {
1611

17-
Document convertResponse(response::Value&& response);
12+
std::string toJSON(Value&& response);
1813

19-
response::Value convertResponse(const Document& document);
14+
Value parseJSON(const std::string& json);
2015

21-
} /* namespace rapidjson */
16+
} /* namespace response */
2217
} /* namespace graphql */
2318
} /* namespace facebook */

0 commit comments

Comments
 (0)