From 3b87d04ad637e08977932d160257e982fd640676 Mon Sep 17 00:00:00 2001 From: MouriNaruto Date: Thu, 18 Apr 2024 23:57:59 +0800 Subject: [PATCH] Implement NanaGet.JsonRpc2. --- NanaGet/NanaGet.JsonRpc2.cpp | 128 +++++++++++++++++++++++++++++++++++ NanaGet/NanaGet.JsonRpc2.h | 90 ++++++++++++++++++++++++ 2 files changed, 218 insertions(+) diff --git a/NanaGet/NanaGet.JsonRpc2.cpp b/NanaGet/NanaGet.JsonRpc2.cpp index 77af618..57f807f 100644 --- a/NanaGet/NanaGet.JsonRpc2.cpp +++ b/NanaGet/NanaGet.JsonRpc2.cpp @@ -9,3 +9,131 @@ */ #include "NanaGet.JsonRpc2.h" + +std::string NanaGet::JsonRpc2::FromRequestMessage( + NanaGet::JsonRpc2::RequestMessage const& Value) +{ + try + { + nlohmann::json ResultJson; + ResultJson["jsonrpc"] = "2.0"; + ResultJson["method"] = Value.Method; + ResultJson["params"] = nlohmann::json::parse(Value.Parameters); + if (!Value.IsNotification) + { + ResultJson["id"] = Value.Identifier; + } + return ResultJson.dump(2); + } + catch (...) + { + return std::string(); + } +} + +std::string NanaGet::JsonRpc2::FromErrorMessage( + NanaGet::JsonRpc2::ErrorMessage const& Value) +{ + try + { + nlohmann::json ResultJson; + ResultJson["code"] = Value.Code; + ResultJson["message"] = Value.Message; + ResultJson["data"] = Value.Data; + return ResultJson.dump(2); + } + catch (...) + { + return std::string(); + } +} + +NanaGet::JsonRpc2::ErrorMessage NanaGet::JsonRpc2::ToErrorMessage( + nlohmann::json const& Value) +{ + NanaGet::JsonRpc2::ErrorMessage Result; + + try + { + Result.Code = Value.at("code").get(); + } + catch (...) + { + + } + + try + { + Result.Message = Value.at("message").get(); + } + catch (...) + { + + } + + try + { + Result.Data = Value.at("data").get(); + } + catch (...) + { + + } + + return Result; +} + +NanaGet::JsonRpc2::ResponseMessage NanaGet::JsonRpc2::ToResponseMessage( + nlohmann::json const& Value) +{ + NanaGet::JsonRpc2::ResponseMessage Result; + + if (Value.contains("jsonrpc") && + "2.0" == Value["jsonrpc"].get()) + { + Result.IsSucceeded = Value.contains("result"); + if (Result.IsSucceeded) + { + try + { + Result.Message = Value.at("result").get(); + } + catch (...) + { + + } + } + else + { + try + { + Result.Message = Value.at("error").get(); + } + catch (...) + { + NanaGet::JsonRpc2::ErrorMessage Error; + Error.Code = -32603; + Error.Message = "Unspecified error."; + Result.Message = NanaGet::JsonRpc2::FromErrorMessage(Error); + } + } + + try + { + Result.Identifier = Value.at("id").get(); + } + catch (...) + { + + } + } + else + { + NanaGet::JsonRpc2::ErrorMessage Error; + Error.Code = -32603; + Error.Message = "Invalid JSON-RPC 2.0 response message."; + Result.Message = NanaGet::JsonRpc2::FromErrorMessage(Error); + } + + return Result; +} diff --git a/NanaGet/NanaGet.JsonRpc2.h b/NanaGet/NanaGet.JsonRpc2.h index 7115c45..af77d2f 100644 --- a/NanaGet/NanaGet.JsonRpc2.h +++ b/NanaGet/NanaGet.JsonRpc2.h @@ -17,11 +17,101 @@ #error "[NanaGet.JsonRpc2] You should use a C++ compiler with the C++17 standard." #endif +#include +#include + #include namespace NanaGet::JsonRpc2 { + /** + * @brief The request message of a JSON-RPC 2.0 call. + */ + struct RequestMessage + { + /** + * @brief true if this request is a notification. Otherwise false. + */ + bool IsNotification = false; + /** + * @brief A string containing the name of the method to be invoked. + * method names that begin with the word rpc followed by a period + * character (U+002E or ASCII 46) are reserved for rpc-internal + * methods and extensions and MUST NOT be used for anything else. + */ + std::string Method; + /** + * @brief A structured JSON value that holds the parameter values to be + * used during the invocation of the method. This member MAY be + * omitted. + */ + std::string Parameters; + /** + * @brief An identifier established by the client. If it is not included + * it is assumed to be a notification. The value SHOULD normally + * not be NULL and Numbers SHOULD NOT contain fractional parts. + */ + std::string Identifier; + }; + + std::string FromRequestMessage( + RequestMessage const& Value); + + /** + * @brief The message returned when a JSON-RPC 2.0 call encounters an error. + */ + struct ErrorMessage + { + /** + * @brief A number that indicates the error type that occurred. + */ + std::int64_t Code; + /** + * @brief A string providing a short description of the error. The + * message SHOULD be limited to a concise single sentence. + */ + std::string Message; + /** + * @brief A primitive or structured JSON value that contains additional + * information about the error. This may be omitted. The value + * of this member is defined by the Server (e.g. detailed error + * information, nested errors etc.). + */ + std::string Data; + }; + + std::string FromErrorMessage( + ErrorMessage const& Value); + + ErrorMessage ToErrorMessage( + nlohmann::json const& Value); + + /** + * @brief The response message of a JSON-RPC 2.0 call. + */ + struct ResponseMessage + { + /** + * @brief true if this JSON-RPC 2.0 call is succeed. Otherwise false. + */ + bool IsSucceeded = false; + /** + * @brief The value of this member is determined by the method invoked + * on the Server if IsSucceeded is true, or return a JSON string + * which represents ErrorMessage. + */ + std::string Message; + /** + * @brief It MUST be the same as the value of the id member in the + * request message. If there was an error in detecting the id + * in the request message (e.g. Parse error/Invalid Request), + * it MUST be NULL. + */ + std::string Identifier; + }; + ResponseMessage ToResponseMessage( + nlohmann::json const& Value); } #endif // !NANAGET_JSONRPC2