Browse Source

#IQRV #comment [libRestfulFunc] 支持 Ojbect2Json

gifur 3 years ago
parent
commit
0bcda46c71

+ 91 - 6
Other/libRestfulFunc/JsonConvertHelper.hpp

@@ -9,10 +9,19 @@
 #define JSONCONVERT2OBJECT_MEMEBER_REGISTER(...)  \
 bool JSONCONVERT2OBJECT_MEMEBER_REGISTER_RESERVERD_IMPLE(const Json::Value& jsonTypeValue, std::vector<std::string> &names) \
 {     \
-    if(names.size() <= 0)   \
+    if(names.size() <= 0)  { \
         names = Member2KeyParseWithStr(#__VA_ARGS__); \
+    }   \
     return JsonParse(names, 0, jsonTypeValue, __VA_ARGS__); \
-} 
+}   \
+bool OBJECTCONVERT2JSON_MEMEBER_REGISTER_RESERVERD_IMPLE(Json::Value& jsonTypeValue, std::vector<std::string> &names) const \
+{     \
+    if(names.size() <= 0)  { \
+        names = Member2KeyParseWithStr(#__VA_ARGS__); \
+    }   \
+    return ParseJson(names, 0, jsonTypeValue, __VA_ARGS__); \
+}   \
+
 
 #define JSONCONVERT2OBJECT_MEMEBER_RENAME_REGISTER(...)  \
 std::vector<std::string> JSONCONVERT2OBJECT_MEMEBER_RENAME_REGISTER_RESERVERD_IMPLE() const \
@@ -90,6 +99,7 @@ static std::vector<std::string> Member2KeyParseWithStr(const std::string& values
     auto enumValues = NormalStringSplit(values, ',');
     result.reserve(enumValues.size());
     for (auto const& enumValue : enumValues) {
+        /** 修复喜欢加空格或代码格式化导致的问题 [Gifur@2022122]*/
         result.push_back(NormalStringTrim(enumValue));
     }
     return result;
@@ -106,6 +116,12 @@ static bool Json2Object(bool& aimObj, const Json::Value& jsonTypeValue)
         return true;
     }
 }
+static bool Object2Json(Json::Value& jsonTypeValue, const std::string& key, bool value)
+{
+    jsonTypeValue[key] = value;
+    return true;
+}
+
 static bool Json2Object(int& aimObj, const Json::Value& jsonTypeValue)
 {
     if (jsonTypeValue.isNull() || !jsonTypeValue.isInt()) {
@@ -115,6 +131,12 @@ static bool Json2Object(int& aimObj, const Json::Value& jsonTypeValue)
         return true;
     }
 }
+static bool Object2Json(Json::Value& jsonTypeValue, const std::string& key, const int& value)
+{
+    jsonTypeValue[key] = value;
+    return true;
+}
+
 static bool Json2Object(unsigned int& aimObj, const Json::Value& jsonTypeValue)
 {
     if (jsonTypeValue.isNull() || !jsonTypeValue.isUInt()) {
@@ -124,6 +146,12 @@ static bool Json2Object(unsigned int& aimObj, const Json::Value& jsonTypeValue)
         return true;
     }
 }
+static bool Object2Json(Json::Value& jsonTypeValue, const std::string& key, const unsigned int& value)
+{
+    jsonTypeValue[key] = value;
+    return true;
+}
+
 static bool Json2Object(double& aimObj, const Json::Value& jsonTypeValue)
 {
     if (jsonTypeValue.isNull() || !jsonTypeValue.isDouble()) {
@@ -133,6 +161,12 @@ static bool Json2Object(double& aimObj, const Json::Value& jsonTypeValue)
         return true;
     }
 }
+static bool Object2Json(Json::Value& jsonTypeValue, const std::string& key, const double& value)
+{
+    jsonTypeValue[key] = value;
+    return true;
+}
+
 static bool Json2Object(std::string& aimObj, const Json::Value& jsonTypeValue)
 {
     if (jsonTypeValue.isNull() || !jsonTypeValue.isString()) {
@@ -142,16 +176,20 @@ static bool Json2Object(std::string& aimObj, const Json::Value& jsonTypeValue)
         return true;
     }
 }
-
+static bool Object2Json(Json::Value& jsonTypeValue, const std::string& key, const std::string& value)
+{
+    jsonTypeValue[key] = value;
+    return true;
+}
 
 template <typename TClass, typename enable_if<HasConverFunction<TClass>::has2, int>::type = 0>
-static inline std::vector<std::string> PreGetCustomMemberNameIfExists(TClass& aimObj)
+static inline std::vector<std::string> PreGetCustomMemberNameIfExists(const TClass& aimObj)
 {
     return aimObj.JSONCONVERT2OBJECT_MEMEBER_RENAME_REGISTER_RESERVERD_IMPLE();
 }
 
 template <typename TClass, typename enable_if<!HasConverFunction<TClass>::has2, int>::type = 0>
-static inline std::vector<std::string> PreGetCustomMemberNameIfExists(TClass& aimObj)
+static inline std::vector<std::string> PreGetCustomMemberNameIfExists(const TClass& aimObj)
 {
     return std::vector<std::string>();
 }
@@ -228,12 +266,59 @@ bool Json2Object(TClass& aimObj, const std::string& jsonTypeStr)
 }
 ////////////////////////////////////////////////////////////////////////
 
+template <typename TClass, typename enable_if<HasConverFunction<TClass>::has, int>::type = 0>
+static inline bool Object2Json(Json::Value& jsonTypeOutValue, const std::string& key, const TClass& objValue)
+{
+    std::vector<std::string> names = PreGetCustomMemberNameIfExists(objValue);
+    return objValue.OBJECTCONVERT2JSON_MEMEBER_REGISTER_RESERVERD_IMPLE(jsonTypeOutValue, names);
+}
+
+template <typename TClass, typename enable_if<!HasConverFunction<TClass>::has, int>::type = 0>
+static inline bool Object2Json(Json::Value& jsonTypeOutValue, const std::string& key, const TClass& objValue)
+{
+    return false;
+}
+
+template <typename T>
+static bool ParseJson(const std::vector<std::string>& names, int index, Json::Value& jsonTypeValue, const T& arg)
+{
+    if (names.size() > index) {
+        const std::string key = names[index];
+        ///**TODO(Gifur@1/22/2022): 需要扩展其他类型实现,这里不直接用 JsonCPP 的内容,要考虑到其他自定义结构体 */
+        return Object2Json(jsonTypeValue, key, arg);
+    } else {
+        return false;
+    }
+}
+
+template <typename T, typename... Args>
+static bool ParseJson(const std::vector<std::string>& names, int index, Json::Value& jsonTypeValue, T& arg, Args&... args)
+{
+    if (names.size() - (index + 0) != 1 + sizeof...(Args)) {
+        return false;
+    }
+    /** 通过低柜调用实现 [Gifur@2022122]*/
+    const std::string key = names[index];
+    Object2Json(jsonTypeValue, key, arg);
+
+    return ParseJson(names, index + 1, jsonTypeValue, args...);
+}
 
 /** Provider interface*/
 template<typename T>
 bool Object2Json(std::string& jsonTypeStr, const T& obj)
 {
-    return false;
+    //std::function<Json::Value()>placehoder = [&]()->Json::Value { return Json::Value(); };
+    //auto func = [&](std::function<Json::Value()>f) { return f(); };
+    //Json::Value val = func(placehoder);
+
+    Json::StyledWriter writer;
+    Json::Value root;
+    const bool result = Object2Json(root, "", obj);
+    if (result) {
+        jsonTypeStr = writer.write(root);
+    }
+    return result;
 }
 
 #define __func_1(func,member)   func(member);

+ 87 - 0
Other/libRestfulFunc/RestfulFunc.h

@@ -39,4 +39,91 @@ RESTFULFUNC_API int HttpProbe(const std::string& url, std::string& out_msg, uint
  */
 RESTFULFUNC_API int PingTest(const std::string& dst_ip);
 
+enum HttpRequestMethod
+{
+    GET,
+    POST,
+    PUT,
+    DEL,
+    HEAD,
+    OPTIONS,
+    TRCE,
+    CONNECT,
+    MERGE,
+    PATCH
+};
+
+enum HttpStatusCode : int
+{
+    Continue = 100,
+    SwitchingProtocols = 101,
+    OK = 200,
+    Created = 201,
+    Accepted = 202,
+    NonAuthInfo = 203,
+    NoContent = 204,
+    ResetContent = 205,
+    PartialContent = 206,
+    MultiStatus = 207,
+    AlreadyReported = 208,
+    MultipleChoices = 300,
+    MovedPermanently = 301,
+    Found = 302,
+    SeeOther = 303,
+    NotModified = 304,
+    UseProxy = 305,
+    Forbidden = 403,
+    NotFound = 404,
+    ServiceUnavailable = 503
+};
+
+struct HttpClientRequestConfig
+{
+    /*
+    * Start with "http://" or "https://"
+    */
+    HttpClientRequestConfig(const std::string& uri) :mMethod(HttpRequestMethod::GET), mUri(uri) {}
+    HttpClientRequestConfig(HttpRequestMethod method) : mMethod(method) {}
+    HttpClientRequestConfig(HttpRequestMethod method, const std::string& uri) :mMethod(method), mUri(uri) {}
+
+    void SetRequestType(HttpRequestMethod method) { mMethod = method; }
+    void SetUri(const std::string& uri) { mUri = uri; }
+    void SetChildUri(const std::string& subUri) { mSubUri = subUri; }
+
+    std::string GetBaseUri() const { return mUri; }
+    std::string GetSubUri() const { return mSubUri; }
+
+    HttpRequestMethod GetType() const { return mMethod; }
+
+private:
+
+    HttpRequestMethod mMethod;
+    std::string mUri;
+    std::string mSubUri;
+
+};
+
+struct HttpClientResponseResult
+{
+    int statusCode;
+    std::string content;
+};
+
+class RESTFULFUNC_API RestfulClient
+{
+
+public:
+
+    static RestfulClient& getInstance(); // Singleton
+    ~RestfulClient();
+
+    void Do(const HttpClientRequestConfig& requestConfig, HttpClientResponseResult& result);
+
+private:
+    RestfulClient();
+
+private:
+
+};
+
 #endif //_OTHER_RESFULFUNCEXPORT_HEADER_

+ 110 - 1
Other/libRestfulFunc/RestfulFuncImpl.cpp

@@ -1 +1,110 @@
-#include "RestfulFunc.h"
+#include "RestfulFunc.h"
+#include <cpprest/http_client.h>
+
+using namespace utility;                    // Common utilities like string conversions
+using namespace web;                        // Common features like URIs.
+using namespace web::http;                  // Common HTTP functionality
+using namespace web::http::client;          // HTTP client features
+
+RestfulClient& RestfulClient::getInstance()
+{
+    static RestfulClient c;
+    return c;
+}
+
+RestfulClient::RestfulClient()
+{
+
+}
+
+RestfulClient::~RestfulClient()
+{
+
+}
+
+namespace
+{
+    const http::method MappingHttpRequestMethod(HttpRequestMethod provideMethod)
+    {
+        switch (provideMethod) {
+        case GET:
+            return http::methods::GET;
+            break;
+        case POST:
+            return http::methods::POST;
+            break;
+        case PUT:
+            return http::methods::PUT;
+            break;
+        case DEL:
+            return http::methods::DEL;
+            break;
+        case HEAD:
+            return http::methods::HEAD;
+            break;
+        case OPTIONS:
+            return http::methods::OPTIONS;
+            break;
+        case TRCE:
+            return http::methods::TRCE;
+            break;
+        case CONNECT:
+            return http::methods::CONNECT;
+            break;
+        case MERGE:
+            return http::methods::MERGE;
+            break;
+        case PATCH:
+            return http::methods::PATCH;
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void RestfulClient::Do(const HttpClientRequestConfig& requestConfig, HttpClientResponseResult& result)
+{
+    http_client_config config;
+    config.set_validate_certificates(false);
+
+    web::http::client::http_client client(requestConfig.GetBaseUri(), config);
+
+    http_request request(MappingHttpRequestMethod(requestConfig.GetType()));
+    uri_builder urib(requestConfig.GetSubUri());
+    request.set_request_uri(urib.to_string());
+
+    request.headers().add(header_names::accept, "application/json");
+
+    pplx::task<void> requestTask = client.request(request)
+     .then([&result](http_response response) ->pplx::task<json::value> {
+        result.statusCode = response.status_code();
+        if (response.status_code() == status_codes::OK) {
+            return response.extract_json();
+        } else {
+            std::cout << "response status rsult: " << response.status_code() << std::endl;
+            return pplx::task_from_result(json::value());
+        }
+     })
+    .then([&result](pplx::task<json::value> vt) {
+        try {
+
+            json::value const& v = vt.get();
+            result.content = v.to_string();
+
+        } catch (const http_exception& ex) {
+            result.statusCode = -1;
+            result.content = ex.what();
+        }
+    });
+
+     try
+     {
+         requestTask.wait();
+     }
+     catch (const std::exception& ex)
+     {
+         result.statusCode = -1;
+         result.content = ex.what();
+     }
+}

+ 46 - 0
Other/libRestfulFunc/test/testJsonConvert.cpp

@@ -58,4 +58,50 @@ TEST_CASE("test rename class", "[json]")
 }
 
 
+TEST_CASE("test objct 2 json class", "[json]")
+{
+    struct DemoObjct
+    {
+        bool boolValue;
+        int intValue;
+        std::string strValue;
+
+        JSONCONVERT2OBJECT_MEMEBER_REGISTER(boolValue, intValue, strValue)
+            JSONCONVERT2OBJECT_MEMEBER_RENAME_REGISTER("bValue", "iValue", "sValue")
+    };
+
+    DemoObjct demoObj;
+    REQUIRE(Json2Object(demoObj, std::string("{\"bValue\":true, \"iValue\":1234, \"sValue\":\"demo object!\"}")));
+    REQUIRE(demoObj.boolValue == true);
+    REQUIRE(demoObj.intValue == 1234);
+    REQUIRE(demoObj.strValue == "demo object!");
+
+    std::string rawString;
+    REQUIRE(Object2Json(rawString, demoObj));
+    std::cout << "returned json format: " << rawString << std::endl;
+}
+
+TEST_CASE("test objct 2 json  2 class", "[json]")
+{
+    struct DemoObjct
+    {
+        bool boolValue;
+        int intValue;
+        std::string strValue;
+
+        JSONCONVERT2OBJECT_MEMEBER_REGISTER(boolValue, intValue, strValue)
+    };
+
+    DemoObjct demoObj;
+    REQUIRE(Json2Object(demoObj, std::string("{\"boolValue\":true, \"intValue\":1234, \"strValue\":\"demo object!\"}")));
+    REQUIRE(demoObj.boolValue == true);
+    REQUIRE(demoObj.intValue == 1234);
+    REQUIRE(demoObj.strValue == "demo object!");
+
+    std::string rawString;
+    REQUIRE(Object2Json(rawString, demoObj));
+    std::cout << "returned json format: " << rawString << std::endl;
+}
+
+
 

+ 17 - 0
Other/libRestfulFunc/test/testNormlReqAns.cpp

@@ -0,0 +1,17 @@
+#define CATCH_CONFIG_MAIN
+#include <catch2.hpp>
+#include "RestfulFunc.h"
+
+TEST_CASE("test api manage", "[restful]")
+{
+    HttpClientRequestConfig config("https://rvcgateway.paasst.cmbchina.cn/terminal");
+    HttpClientResponseResult result;
+    config.SetChildUri("/api/manage/regist/7555980103");
+    RestfulClient client = RestfulClient::getInstance();
+    client.Do(config, result);
+    std::cout << result.content << std::endl;
+    REQUIRE(!result.content.empty());
+}
+
+
+