X Tutup
// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #include "graphqlservice/JSONResponse.h" #define RAPIDJSON_NAMESPACE graphql::rapidjson #include #include #include #include #include #include #include namespace graphql::response { class StringWriter { public: StringWriter(rapidjson::StringBuffer& buffer) : _writer { buffer } { } void start_object() { _writer.StartObject(); } void add_member(const std::string& key) { _writer.Key(key.c_str()); } void end_object() { _writer.EndObject(); } void start_array() { _writer.StartArray(); } void end_arrary() { _writer.EndArray(); } void write_null() { _writer.Null(); } void write_string(const std::string& value) { _writer.String(value.c_str()); } void write_bool(bool value) { _writer.Bool(value); } void write_int(int value) { _writer.Int(value); } void write_float(double value) { _writer.Double(value); } private: rapidjson::Writer _writer; }; std::string toJSON(Value&& response) { rapidjson::StringBuffer buffer; Writer writer { std::make_unique(buffer) }; writer.write(std::move(response)); return buffer.GetString(); } struct ResponseHandler : rapidjson::BaseReaderHandler, ResponseHandler> { ResponseHandler() { // Start with a single null value. _responseStack.push_back({}); } Value getResponse() { auto response = std::move(_responseStack.back()); _responseStack.pop_back(); return response; } bool Null() { setValue(Value()); return true; } bool Bool(bool b) { setValue(Value(b)); return true; } bool Int(int i) { // https://spec.graphql.org/October2021/#sec-Int static_assert(sizeof(i) == 4, "GraphQL only supports 32-bit signed integers"); auto value = Value(Type::Int); value.set(std::move(i)); setValue(std::move(value)); return true; } bool Uint(unsigned int i) { if (i > static_cast(std::numeric_limits::max())) { // https://spec.graphql.org/October2021/#sec-Int throw std::overflow_error("GraphQL only supports 32-bit signed integers"); } return Int(static_cast(i)); } bool Int64(int64_t /*i*/) { // https://spec.graphql.org/October2021/#sec-Int throw std::overflow_error("GraphQL only supports 32-bit signed integers"); } bool Uint64(uint64_t /*i*/) { // https://spec.graphql.org/October2021/#sec-Int throw std::overflow_error("GraphQL only supports 32-bit signed integers"); } bool Double(double d) { auto value = Value(Type::Float); value.set(std::move(d)); setValue(std::move(value)); return true; } bool String(const Ch* str, rapidjson::SizeType /*length*/, bool /*copy*/) { setValue(Value(std::string(str)).from_json()); return true; } bool StartObject() { _responseStack.push_back(Value(Type::Map)); return true; } bool Key(const Ch* str, rapidjson::SizeType /*length*/, bool /*copy*/) { _keyStack.push_back(str); return true; } bool EndObject(rapidjson::SizeType /*count*/) { setValue(getResponse()); return true; } bool StartArray() { _responseStack.push_back(Value(Type::List)); return true; } bool EndArray(rapidjson::SizeType /*count*/) { setValue(getResponse()); return true; } private: void setValue(Value&& value) { switch (_responseStack.back().type()) { case Type::Map: _responseStack.back().emplace_back(std::move(_keyStack.back()), std::move(value)); _keyStack.pop_back(); break; case Type::List: _responseStack.back().emplace_back(std::move(value)); break; default: _responseStack.back() = std::move(value); break; } } std::vector _keyStack; std::vector _responseStack; }; Value parseJSON(const std::string& json) { ResponseHandler handler; rapidjson::Reader reader; rapidjson::StringStream ss(json.c_str()); reader.Parse(ss, handler); return handler.getResponse(); } } // namespace graphql::response
X Tutup