|
|
@@ -0,0 +1,260 @@
|
|
|
+#ifndef _SP_UTILITY_JSON_CONVERT_HELPER_
|
|
|
+#define _SP_UTILITY_JSON_CONVERT_HELPER_
|
|
|
+
|
|
|
+#include "json/json.h"
|
|
|
+#include <string>
|
|
|
+#include <vector>
|
|
|
+#include <initializer_list>
|
|
|
+
|
|
|
+#define JSONCONVERT2OBJECT_MEMEBER_REGISTER(...) \
|
|
|
+bool JSONCONVERT2OBJECT_MEMEBER_REGISTER_RESERVERD_IMPLE(const Json::Value& jsonTypeValue, std::vector<std::string> &names) \
|
|
|
+{ \
|
|
|
+ if(names.size() <= 0) \
|
|
|
+ names = Member2KeyParseWithStr(#__VA_ARGS__); \
|
|
|
+ return JsonParse(names, 0, jsonTypeValue, __VA_ARGS__); \
|
|
|
+}
|
|
|
+
|
|
|
+#define JSONCONVERT2OBJECT_MEMEBER_RENAME_REGISTER(...) \
|
|
|
+std::vector<std::string> JSONCONVERT2OBJECT_MEMEBER_RENAME_REGISTER_RESERVERD_IMPLE() const \
|
|
|
+{ \
|
|
|
+ return Member2KeyParseWithMultiParam({ __VA_ARGS__ }); \
|
|
|
+}
|
|
|
+
|
|
|
+template <bool, class TYPE = void>
|
|
|
+struct enable_if
|
|
|
+{
|
|
|
+};
|
|
|
+template <class TYPE>
|
|
|
+struct enable_if<true, TYPE>
|
|
|
+{
|
|
|
+ typedef TYPE type;
|
|
|
+};
|
|
|
+
|
|
|
+template <typename T>
|
|
|
+struct HasConverFunction
|
|
|
+{
|
|
|
+ template <typename TT>
|
|
|
+ static char func(decltype(&TT::JSONCONVERT2OBJECT_MEMEBER_REGISTER_RESERVERD_IMPLE)); //@1
|
|
|
+
|
|
|
+ template <typename TT>
|
|
|
+ static int func(...); //@2
|
|
|
+ /*
|
|
|
+ * 如果类型T没有 JSONCONVERT2OBJECT_MEMEBER_REGISTER_RESERVERD_IMPLE 方法,
|
|
|
+ * func<T>(NULL) 匹配 @1 时会产生错误,由于 SFINAE 准则,只能匹配@2
|
|
|
+ * 的func,此时返回值 4 个字节,has 变量为 false,反之,has 变量为 true
|
|
|
+ */
|
|
|
+ const static bool has = (sizeof(func<T>(NULL)) == sizeof(char));
|
|
|
+
|
|
|
+ template <typename TT>
|
|
|
+ static char func2(decltype(&TT::JSONCONVERT2OBJECT_MEMEBER_RENAME_REGISTER_RESERVERD_IMPLE)); //@1
|
|
|
+ template <typename TT>
|
|
|
+ static int func2(...); //@2
|
|
|
+ const static bool has2 = (sizeof(func2<T>(NULL)) == sizeof(char));
|
|
|
+};
|
|
|
+
|
|
|
+static std::vector<std::string> Member2KeyParseWithMultiParam(std::initializer_list<std::string> il)
|
|
|
+{
|
|
|
+ std::vector<std::string> result;
|
|
|
+ for (auto it = il.begin(); it != il.end(); it++) {
|
|
|
+ result.push_back(*it);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+inline static std::string NormalStringTrim(std::string const& str)
|
|
|
+{
|
|
|
+ static char const* whitespaceChars = "\n\r\t ";
|
|
|
+ std::string::size_type start = str.find_first_not_of(whitespaceChars);
|
|
|
+ std::string::size_type end = str.find_last_not_of(whitespaceChars);
|
|
|
+ return start != std::string::npos ? str.substr(start, 1 + end - start) : std::string();
|
|
|
+}
|
|
|
+
|
|
|
+inline static std::vector<std::string> NormalStringSplit(std::string str, char splitElem)
|
|
|
+{
|
|
|
+ std::vector<std::string> strs;
|
|
|
+ std::string::size_type pos1, pos2;
|
|
|
+ pos2 = str.find(splitElem);
|
|
|
+ pos1 = 0;
|
|
|
+ while (std::string::npos != pos2) {
|
|
|
+ strs.push_back(str.substr(pos1, pos2 - pos1));
|
|
|
+ pos1 = pos2 + 1;
|
|
|
+ pos2 = str.find(splitElem, pos1);
|
|
|
+ }
|
|
|
+ strs.push_back(str.substr(pos1));
|
|
|
+ return strs;
|
|
|
+}
|
|
|
+
|
|
|
+static std::vector<std::string> Member2KeyParseWithStr(const std::string& values)
|
|
|
+{
|
|
|
+ std::vector<std::string> result;
|
|
|
+ auto enumValues = NormalStringSplit(values, ',');
|
|
|
+ result.reserve(enumValues.size());
|
|
|
+ for (auto const& enumValue : enumValues) {
|
|
|
+ result.push_back(NormalStringTrim(enumValue));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+//////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+static bool Json2Object(bool& aimObj, const Json::Value& jsonTypeValue)
|
|
|
+{
|
|
|
+ if (jsonTypeValue.isNull() || !jsonTypeValue.isBool()) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ aimObj = jsonTypeValue.asBool();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+static bool Json2Object(int& aimObj, const Json::Value& jsonTypeValue)
|
|
|
+{
|
|
|
+ if (jsonTypeValue.isNull() || !jsonTypeValue.isInt()) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ aimObj = jsonTypeValue.asInt();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+static bool Json2Object(unsigned int& aimObj, const Json::Value& jsonTypeValue)
|
|
|
+{
|
|
|
+ if (jsonTypeValue.isNull() || !jsonTypeValue.isUInt()) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ aimObj = jsonTypeValue.asUInt();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+static bool Json2Object(double& aimObj, const Json::Value& jsonTypeValue)
|
|
|
+{
|
|
|
+ if (jsonTypeValue.isNull() || !jsonTypeValue.isDouble()) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ aimObj = jsonTypeValue.asDouble();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+static bool Json2Object(std::string& aimObj, const Json::Value& jsonTypeValue)
|
|
|
+{
|
|
|
+ if (jsonTypeValue.isNull() || !jsonTypeValue.isString()) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ aimObj = jsonTypeValue.asString();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template <typename TClass, typename enable_if<HasConverFunction<TClass>::has2, int>::type = 0>
|
|
|
+static inline std::vector<std::string> PreGetCustomMemberNameIfExists(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)
|
|
|
+{
|
|
|
+ return std::vector<std::string>();
|
|
|
+}
|
|
|
+
|
|
|
+template <typename TClass, typename enable_if<HasConverFunction<TClass>::has, int>::type = 0>
|
|
|
+static inline bool Json2Object(TClass& aimObj, const Json::Value& jsonTypeValue)
|
|
|
+{
|
|
|
+ std::vector<std::string> names = PreGetCustomMemberNameIfExists(aimObj);
|
|
|
+ return aimObj.JSONCONVERT2OBJECT_MEMEBER_REGISTER_RESERVERD_IMPLE(jsonTypeValue, names);
|
|
|
+}
|
|
|
+
|
|
|
+template <typename TClass, typename enable_if<!HasConverFunction<TClass>::has, int>::type = 0>
|
|
|
+static inline bool Json2Object(TClass& aimObj, const Json::Value& jsonTypeValue)
|
|
|
+{
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+template <typename T>
|
|
|
+static bool Json2Object(std::vector<T>& aimObj, const Json::Value& jsonTypeValue)
|
|
|
+{
|
|
|
+ if (jsonTypeValue.isNull() || !jsonTypeValue.isArray()) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+
|
|
|
+ aimObj.clear();
|
|
|
+
|
|
|
+ bool result(true);
|
|
|
+
|
|
|
+ for (int i = 0; i < jsonTypeValue.size(); ++i) {
|
|
|
+ T item;
|
|
|
+ if (!Json2Object(item, jsonTypeValue[i])) {
|
|
|
+ result = false;
|
|
|
+ }
|
|
|
+ aimObj.push_back(item);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+template <typename T>
|
|
|
+static bool JsonParse(const std::vector<std::string>& names, int index, const Json::Value& jsonTypeValue, T& arg)
|
|
|
+{
|
|
|
+ const auto key = names[index];
|
|
|
+ if (!jsonTypeValue.isMember(key) || Json2Object(arg, jsonTypeValue[key])) {
|
|
|
+ return true;
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+template <typename T, typename... Args>
|
|
|
+static bool JsonParse(const std::vector<std::string>& names, int index, const Json::Value& jsonTypeValue, T& arg, Args&... args)
|
|
|
+{
|
|
|
+ if (!JsonParse(names, index, jsonTypeValue, arg)) {
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ return JsonParse(names, index + 1, jsonTypeValue, args...);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/** Provider interface*/
|
|
|
+template<typename TClass>
|
|
|
+bool Json2Object(TClass& aimObj, const std::string& jsonTypeStr)
|
|
|
+{
|
|
|
+ Json::Reader reader;
|
|
|
+ Json::Value root;
|
|
|
+
|
|
|
+ if (!reader.parse(jsonTypeStr, root) || root.isNull()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return Json2Object(aimObj, root);
|
|
|
+}
|
|
|
+////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+
|
|
|
+/** Provider interface*/
|
|
|
+template<typename T>
|
|
|
+bool Object2Json(std::string& jsonTypeStr, const T& obj)
|
|
|
+{
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+#define __func_1(func,member) func(member);
|
|
|
+#define __func_2(func,member,...) __func_1(func,member) __func_1(func,__VA_ARGS__)
|
|
|
+#define __func_3(func,member,...) __func_1(func,member) __func_2(func,__VA_ARGS__)
|
|
|
+#define __func_4(func,member,...) __func_1(func,member) __func_3(func,__VA_ARGS__)
|
|
|
+#define __func_5(func,member,...) __func_1(func,member) __func_4(func,__VA_ARGS__)
|
|
|
+
|
|
|
+//eg: COUNT(a,b,c) === 3
|
|
|
+#define COUNT(...) __count__(0, ##__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
|
|
+#define __count__(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
|
|
|
+
|
|
|
+#define __macro_cat__(a,b) a##b
|
|
|
+#define MACRO_CAT(a,b) __macro_cat__(a,b)
|
|
|
+
|
|
|
+#define FOR_EACH(func,...) \
|
|
|
+ MACRO_CAT(__func_,COUNT(__VA_ARGS__))(func, __VA_ARGS__)
|
|
|
+
|
|
|
+#define JSON2OBJECT_EACH_FILED__(field) \
|
|
|
+ if(!::Json2Object(field, jsonTypeValue[#field])){ \
|
|
|
+ result = false; \
|
|
|
+ }
|
|
|
+
|
|
|
+#endif //_SP_UTILITY_JSON_CONVERT_HELPER_
|