1000 lines
36 KiB
C++
1000 lines
36 KiB
C++
#pragma once
|
|
#include <list>
|
|
#include <map>
|
|
#include <vector>
|
|
#include <string>
|
|
#include <iostream>
|
|
#include <unordered_map>
|
|
|
|
#include <rapidjson/document.h>
|
|
#include <rapidjson/writer.h>
|
|
#include <rapidjson/stringbuffer.h>
|
|
#include <rapidjson/prettywriter.h>
|
|
|
|
namespace aigc {
|
|
|
|
/******************************************************
|
|
* Register class or struct members
|
|
* eg:
|
|
* struct Test
|
|
* {
|
|
* string A;
|
|
* string B;
|
|
* AIGC_JSON_HELPER(A, B)
|
|
* };
|
|
******************************************************/
|
|
#define AIGC_JSON_HELPER(...) \
|
|
std::map<std::string, std::string> __aigcDefaultValues; \
|
|
bool AIGCJsonToObject(aigc::JsonHelperPrivate &handle, \
|
|
rapidjson::Value &jsonValue, \
|
|
std::vector<std::string> &names) { \
|
|
std::vector<std::string> standardNames = handle.GetMembersNames(#__VA_ARGS__); \
|
|
if (names.size() <= standardNames.size()) { \
|
|
for (int i = static_cast<int>(names.size()); i < static_cast<int>(standardNames.size()); i++) \
|
|
names.push_back(standardNames[i]); \
|
|
} \
|
|
return handle.SetMembers(names, 0, jsonValue, __aigcDefaultValues, __VA_ARGS__); \
|
|
} \
|
|
bool AIGCObjectToJson(aigc::JsonHelperPrivate &handle, \
|
|
rapidjson::Value &jsonValue, \
|
|
rapidjson::Document::AllocatorType &allocator, \
|
|
std::vector<std::string> &names) { \
|
|
std::vector<std::string> standardNames = handle.GetMembersNames(#__VA_ARGS__); \
|
|
if (names.size() <= standardNames.size()) { \
|
|
for (int i = static_cast<int>(names.size()); i < static_cast<int>(standardNames.size()); i++) \
|
|
names.push_back(standardNames[i]); \
|
|
} \
|
|
return handle.GetMembers(names, 0, jsonValue, allocator, __VA_ARGS__); \
|
|
}
|
|
|
|
/******************************************************
|
|
* Rename members
|
|
* eg:
|
|
* struct Test
|
|
* {
|
|
* string A;
|
|
* string B;
|
|
* AIGC_JSON_HELPER(A, B)
|
|
* AIGC_JSON_HELPER_RENAME("a", "b")
|
|
* };
|
|
******************************************************/
|
|
#define AIGC_JSON_HELPER_RENAME(...) \
|
|
std::vector<std::string> AIGCRenameMembers(aigc::JsonHelperPrivate &handle) { \
|
|
return handle.GetMembersNames(#__VA_ARGS__); \
|
|
}
|
|
|
|
/******************************************************
|
|
* Register base-class
|
|
* eg:
|
|
* struct Base
|
|
* {
|
|
* string name;
|
|
* AIGC_JSON_HELPER(name)
|
|
* };
|
|
* struct Test : Base
|
|
* {
|
|
* string A;
|
|
* string B;
|
|
* AIGC_JSON_HELPER(A, B)
|
|
* AIGC_JSON_HELPER_BASE((Base*)this)
|
|
* };
|
|
******************************************************/
|
|
#define AIGC_JSON_HELPER_BASE(...) \
|
|
bool AIGCBaseJsonToObject(aigc::JsonHelperPrivate &handle, rapidjson::Value &jsonValue) { \
|
|
return handle.SetBase(jsonValue, __VA_ARGS__); \
|
|
} \
|
|
bool AIGCBaseObjectToJson(aigc::JsonHelperPrivate &handle, \
|
|
rapidjson::Value &jsonValue, \
|
|
rapidjson::Document::AllocatorType &allocator) { \
|
|
return handle.GetBase(jsonValue, allocator, __VA_ARGS__); \
|
|
}
|
|
|
|
/******************************************************
|
|
* Set default value
|
|
* eg:
|
|
* struct Base
|
|
* {
|
|
* string name;
|
|
* int age;
|
|
* AIGC_JSON_HELPER(name, age)
|
|
* AIGC_JSON_HELPER_DEFAULT(age=18)
|
|
* };
|
|
******************************************************/
|
|
#define AIGC_JSON_HELPER_DEFAULT(...) \
|
|
void AIGCDefaultValues(aigc::JsonHelperPrivate &handle) { \
|
|
__aigcDefaultValues = handle.GetMembersValueMap(#__VA_ARGS__); \
|
|
}
|
|
|
|
class JsonHelperPrivate {
|
|
public:
|
|
/******************************************************
|
|
*
|
|
* enable_if
|
|
*
|
|
******************************************************/
|
|
template<bool, class TYPE = void> struct enable_if {};
|
|
|
|
template<class TYPE> struct enable_if<true, TYPE> {
|
|
typedef TYPE type;
|
|
};
|
|
|
|
public:
|
|
/******************************************************
|
|
*
|
|
* Check Interface
|
|
* If class or struct add AIGC_JSON_HELPER\AIGC_JSON_HELPER_RENAME\AIGC_JSON_HELPER_BASE,
|
|
* it will go to the correct conver function.
|
|
*
|
|
******************************************************/
|
|
template<typename T> struct HasConverFunction {
|
|
template<typename TT> static char func(decltype(&TT::AIGCJsonToObject));
|
|
|
|
template<typename TT> static int func(...);
|
|
|
|
const static bool has = (sizeof(func<T>(NULL)) == sizeof(char));
|
|
};
|
|
|
|
template<typename T> struct HasRenameFunction {
|
|
template<typename TT> static char func(decltype(&TT::AIGCRenameMembers));
|
|
template<typename TT> static int func(...);
|
|
const static bool has = (sizeof(func<T>(NULL)) == sizeof(char));
|
|
};
|
|
|
|
template<typename T> struct HasBaseConverFunction {
|
|
template<typename TT> static char func(decltype(&TT::AIGCBaseJsonToObject));
|
|
template<typename TT> static int func(...);
|
|
const static bool has = (sizeof(func<T>(NULL)) == sizeof(char));
|
|
};
|
|
|
|
template<typename T> struct HasDefaultValueFunction {
|
|
template<typename TT> static char func(decltype(&TT::AIGCDefaultValues));
|
|
template<typename TT> static int func(...);
|
|
const static bool has = (sizeof(func<T>(NULL)) == sizeof(char));
|
|
};
|
|
|
|
public:
|
|
/******************************************************
|
|
*
|
|
* Interface of JsonToObject\ObjectToJson
|
|
*
|
|
******************************************************/
|
|
template<typename T, typename enable_if<HasConverFunction<T>::has, int>::type = 0>
|
|
bool JsonToObject(T &obj, rapidjson::Value &jsonValue) {
|
|
if (!BaseConverJsonToObject(obj, jsonValue)) {
|
|
return false;
|
|
}
|
|
|
|
LoadDefaultValuesMap(obj);
|
|
std::vector<std::string> names = LoadRenameArray(obj);
|
|
return obj.AIGCJsonToObject(*this, jsonValue, names);
|
|
}
|
|
|
|
template<typename T, typename enable_if<!HasConverFunction<T>::has, int>::type = 0>
|
|
bool JsonToObject(T &obj, rapidjson::Value &jsonValue) {
|
|
if (std::is_enum<T>::value) {
|
|
int ivalue;
|
|
if (!JsonToObject(ivalue, jsonValue)) {
|
|
return false;
|
|
}
|
|
|
|
obj = static_cast<T>(ivalue);
|
|
return true;
|
|
}
|
|
|
|
m_message = "unsupported this type.";
|
|
return false;
|
|
}
|
|
|
|
template<typename T, typename enable_if<HasConverFunction<T>::has, int>::type = 0>
|
|
bool ObjectToJson(T &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
if (jsonValue.IsNull()) {
|
|
jsonValue.SetObject();
|
|
}
|
|
if (!BaseConverObjectToJson(obj, jsonValue, allocator)) {
|
|
return false;
|
|
}
|
|
std::vector<std::string> names = LoadRenameArray(obj);
|
|
return obj.AIGCObjectToJson(*this, jsonValue, allocator, names);
|
|
}
|
|
|
|
template<typename T, typename enable_if<!HasConverFunction<T>::has, int>::type = 0>
|
|
bool ObjectToJson(T &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
if (std::is_enum<T>::value) {
|
|
int ivalue = static_cast<int>(obj);
|
|
return ObjectToJson(ivalue, jsonValue, allocator);
|
|
}
|
|
|
|
m_message = "unsupported this type.";
|
|
return false;
|
|
}
|
|
|
|
/******************************************************
|
|
*
|
|
* Interface of LoadRenameArray
|
|
*
|
|
******************************************************/
|
|
template<typename T, typename enable_if<HasRenameFunction<T>::has, int>::type = 0>
|
|
std::vector<std::string> LoadRenameArray(T &obj) {
|
|
return obj.AIGCRenameMembers(*this);
|
|
}
|
|
|
|
template<typename T, typename enable_if<!HasRenameFunction<T>::has, int>::type = 0>
|
|
std::vector<std::string> LoadRenameArray(T &obj) {
|
|
return std::vector<std::string>();
|
|
}
|
|
|
|
/******************************************************
|
|
*
|
|
* Interface of BaseConverJsonToObject\BaseConverObjectToJson
|
|
*
|
|
******************************************************/
|
|
template<typename T, typename enable_if<HasBaseConverFunction<T>::has, int>::type = 0>
|
|
bool BaseConverJsonToObject(T &obj, rapidjson::Value &jsonValue) {
|
|
return obj.AIGCBaseJsonToObject(*this, jsonValue);
|
|
}
|
|
|
|
template<typename T, typename enable_if<!HasBaseConverFunction<T>::has, int>::type = 0>
|
|
bool BaseConverJsonToObject(T &obj, rapidjson::Value &jsonValue) {
|
|
return true;
|
|
}
|
|
|
|
template<typename T, typename enable_if<HasBaseConverFunction<T>::has, int>::type = 0>
|
|
bool BaseConverObjectToJson(T &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
return obj.AIGCBaseObjectToJson(*this, jsonValue, allocator);
|
|
}
|
|
|
|
template<typename T, typename enable_if<!HasBaseConverFunction<T>::has, int>::type = 0>
|
|
bool BaseConverObjectToJson(T &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
return true;
|
|
}
|
|
|
|
/******************************************************
|
|
*
|
|
* Interface of Default value
|
|
*
|
|
******************************************************/
|
|
template<typename T, typename enable_if<HasDefaultValueFunction<T>::has, int>::type = 0>
|
|
void LoadDefaultValuesMap(T &obj) {
|
|
obj.AIGCDefaultValues(*this);
|
|
}
|
|
|
|
template<typename T, typename enable_if<!HasDefaultValueFunction<T>::has, int>::type = 0>
|
|
void LoadDefaultValuesMap(T &obj) {
|
|
(void)obj;
|
|
}
|
|
|
|
public:
|
|
/******************************************************
|
|
*
|
|
* Tool function
|
|
*
|
|
******************************************************/
|
|
static std::vector<std::string> StringSplit(const std::string &str, char sep = ',') {
|
|
std::vector<std::string> array;
|
|
std::string::size_type pos1, pos2;
|
|
pos1 = 0;
|
|
pos2 = str.find(sep);
|
|
while (std::string::npos != pos2) {
|
|
array.push_back(str.substr(pos1, pos2 - pos1));
|
|
pos1 = pos2 + 1;
|
|
pos2 = str.find(sep, pos1);
|
|
}
|
|
if (pos1 != str.length()) {
|
|
array.push_back(str.substr(pos1));
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
static std::string StringTrim(std::string key) {
|
|
std::string newStr = key;
|
|
if (!newStr.empty()) {
|
|
newStr.erase(0, newStr.find_first_not_of(" "));
|
|
newStr.erase(newStr.find_last_not_of(" ") + 1);
|
|
}
|
|
if (!newStr.empty()) {
|
|
newStr.erase(0, newStr.find_first_not_of("\""));
|
|
newStr.erase(newStr.find_last_not_of("\"") + 1);
|
|
}
|
|
return newStr;
|
|
}
|
|
|
|
static void StringTrim(std::vector<std::string> &array) {
|
|
for (int i = 0; i < (int)array.size(); i++) {
|
|
array[i] = StringTrim(array[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get json value type
|
|
*/
|
|
static std::string GetJsonValueTypeName(rapidjson::Value &jsonValue) {
|
|
switch (jsonValue.GetType()) {
|
|
case rapidjson::Type::kArrayType:
|
|
return "array";
|
|
case rapidjson::Type::kFalseType:
|
|
case rapidjson::Type::kTrueType:
|
|
return "bool";
|
|
case rapidjson::Type::kObjectType:
|
|
return "object";
|
|
case rapidjson::Type::kStringType:
|
|
return "string";
|
|
case rapidjson::Type::kNumberType:
|
|
return "number";
|
|
default:
|
|
return "string";
|
|
}
|
|
}
|
|
|
|
static std::string GetStringFromJsonValue(rapidjson::Value &jsonValue, bool isPrettyWriter = false) {
|
|
rapidjson::StringBuffer buffer;
|
|
|
|
if (isPrettyWriter) {
|
|
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
|
|
jsonValue.Accept(writer);
|
|
} else {
|
|
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
|
jsonValue.Accept(writer);
|
|
}
|
|
|
|
std::string ret = std::string(buffer.GetString());
|
|
return ret;
|
|
}
|
|
|
|
static std::string FindStringFromMap(std::string name, std::map<std::string, std::string> &stringMap) {
|
|
std::map<std::string, std::string>::iterator iter = stringMap.find(name);
|
|
if (iter == stringMap.end()) {
|
|
return "";
|
|
}
|
|
return iter->second;
|
|
}
|
|
|
|
public:
|
|
/******************************************************
|
|
*
|
|
* Set class/struct members value
|
|
*
|
|
******************************************************/
|
|
std::vector<std::string> GetMembersNames(const std::string membersStr) {
|
|
std::vector<std::string> array = StringSplit(membersStr);
|
|
StringTrim(array);
|
|
return array;
|
|
}
|
|
|
|
std::map<std::string, std::string> GetMembersValueMap(const std::string valueStr) {
|
|
std::vector<std::string> array = StringSplit(valueStr);
|
|
std::map<std::string, std::string> ret;
|
|
for (unsigned int i = 0; i < array.size(); i++) {
|
|
std::vector<std::string> keyValue = StringSplit(array[i], '=');
|
|
if (keyValue.size() != 2) {
|
|
continue;
|
|
}
|
|
|
|
std::string key = StringTrim(keyValue[0]);
|
|
std::string value = StringTrim(keyValue[1]);
|
|
if (ret.find(key) != ret.end()) {
|
|
continue;
|
|
}
|
|
ret.insert(std::pair<std::string, std::string>(key, value));
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template<typename TYPE, typename... TYPES>
|
|
bool SetMembers(const std::vector<std::string> &names,
|
|
int index,
|
|
rapidjson::Value &jsonValue,
|
|
std::map<std::string, std::string> defaultValues,
|
|
TYPE &arg,
|
|
TYPES &...args) {
|
|
if (!SetMembers(names, index, jsonValue, defaultValues, arg)) {
|
|
return false;
|
|
}
|
|
|
|
return SetMembers(names, ++index, jsonValue, defaultValues, args...);
|
|
}
|
|
|
|
template<typename TYPE>
|
|
bool SetMembers(const std::vector<std::string> &names,
|
|
int index,
|
|
rapidjson::Value &jsonValue,
|
|
std::map<std::string, std::string> defaultValues,
|
|
TYPE &arg) {
|
|
if (jsonValue.IsNull()) {
|
|
return true;
|
|
}
|
|
|
|
const char *key = names[index].c_str();
|
|
if (!jsonValue.IsObject()) {
|
|
return false;
|
|
}
|
|
if (!jsonValue.HasMember(key)) {
|
|
std::string defaultV = FindStringFromMap(names[index], defaultValues);
|
|
if (!defaultV.empty()) {
|
|
StringToObject(arg, defaultV);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
if (!JsonToObject(arg, jsonValue[key])) {
|
|
m_message = "[" + names[index] + "] " + m_message;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/******************************************************
|
|
*
|
|
* Get class/struct members value
|
|
*
|
|
******************************************************/
|
|
template<typename TYPE, typename... TYPES>
|
|
bool GetMembers(const std::vector<std::string> &names,
|
|
int index,
|
|
rapidjson::Value &jsonValue,
|
|
rapidjson::Document::AllocatorType &allocator,
|
|
TYPE &arg,
|
|
TYPES &...args) {
|
|
if (!GetMembers(names, index, jsonValue, allocator, arg)) {
|
|
return false;
|
|
}
|
|
return GetMembers(names, ++index, jsonValue, allocator, args...);
|
|
}
|
|
|
|
template<typename TYPE>
|
|
bool GetMembers(const std::vector<std::string> &names,
|
|
int index,
|
|
rapidjson::Value &jsonValue,
|
|
rapidjson::Document::AllocatorType &allocator,
|
|
TYPE &arg) {
|
|
rapidjson::Value item;
|
|
bool check = ObjectToJson(arg, item, allocator);
|
|
if (!check) {
|
|
m_message = "[" + names[index] + "] " + m_message;
|
|
return false;
|
|
}
|
|
|
|
if (jsonValue.HasMember(names[index].c_str())) {
|
|
jsonValue.RemoveMember(names[index].c_str());
|
|
}
|
|
|
|
rapidjson::Value key;
|
|
key.SetString(names[index].c_str(), static_cast<rapidjson::SizeType>(names[index].length()), allocator);
|
|
jsonValue.AddMember(key, item, allocator);
|
|
return true;
|
|
}
|
|
|
|
public:
|
|
/******************************************************
|
|
*
|
|
* Set base class value
|
|
*
|
|
******************************************************/
|
|
template<typename TYPE, typename... TYPES> bool SetBase(rapidjson::Value &jsonValue, TYPE *arg, TYPES *...args) {
|
|
if (!SetBase(jsonValue, arg)) {
|
|
return false;
|
|
}
|
|
return SetBase(jsonValue, args...);
|
|
}
|
|
|
|
template<typename TYPE> bool SetBase(rapidjson::Value &jsonValue, TYPE *arg) {
|
|
return JsonToObject(*arg, jsonValue);
|
|
}
|
|
|
|
/******************************************************
|
|
*
|
|
* Get base class value
|
|
*
|
|
******************************************************/
|
|
template<typename TYPE, typename... TYPES>
|
|
bool GetBase(rapidjson::Value &jsonValue,
|
|
rapidjson::Document::AllocatorType &allocator,
|
|
TYPE *arg,
|
|
TYPES *...args) {
|
|
if (!GetBase(jsonValue, allocator, arg)) {
|
|
return false;
|
|
}
|
|
return GetBase(jsonValue, allocator, args...);
|
|
}
|
|
|
|
template<typename TYPE>
|
|
bool GetBase(rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator, TYPE *arg) {
|
|
return ObjectToJson(*arg, jsonValue, allocator);
|
|
}
|
|
|
|
public:
|
|
/******************************************************
|
|
* Conver base-type : string to base-type
|
|
* Contain: int\uint、int64_t\uint64_t、bool、float
|
|
* double、string
|
|
*
|
|
******************************************************/
|
|
template<typename TYPE> void StringToObject(TYPE &obj, std::string &value) {
|
|
return;
|
|
}
|
|
|
|
void StringToObject(std::string &obj, std::string &value) {
|
|
obj = value;
|
|
}
|
|
|
|
void StringToObject(int &obj, std::string &value) {
|
|
obj = atoi(value.c_str());
|
|
}
|
|
|
|
void StringToObject(unsigned int &obj, std::string &value) {
|
|
char *end;
|
|
obj = strtoul(value.c_str(), &end, 10);
|
|
}
|
|
|
|
void StringToObject(int64_t &obj, std::string &value) {
|
|
char *end;
|
|
obj = strtoll(value.c_str(), &end, 10);
|
|
}
|
|
|
|
void StringToObject(uint64_t &obj, std::string &value) {
|
|
char *end;
|
|
obj = strtoull(value.c_str(), &end, 10);
|
|
}
|
|
|
|
void StringToObject(bool &obj, std::string &value) {
|
|
obj = (value == "true");
|
|
}
|
|
|
|
void StringToObject(float &obj, std::string &value) {
|
|
obj = strtof(value.c_str(), nullptr);
|
|
}
|
|
|
|
void StringToObject(double &obj, std::string &value) {
|
|
obj = strtod(value.c_str(), nullptr);
|
|
}
|
|
|
|
public:
|
|
/******************************************************
|
|
* Conver base-type : Json string to base-type
|
|
* Contain: int\uint、int64_t\uint64_t、bool、float
|
|
* double、string、vector、list、map<string,XX>
|
|
*
|
|
******************************************************/
|
|
bool JsonToObject(int &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsInt()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is int.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetInt();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(unsigned int &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsUint()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is unsigned int.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetUint();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(short &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsInt()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is short.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetInt();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(unsigned short &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsUint()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is unsigned short.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetUint();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(int64_t &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsInt64()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is int64_t.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetInt64();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(uint64_t &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsUint64()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is uint64_t.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetUint64();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(bool &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsBool()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is bool.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetBool();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(float &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsNumber()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is float.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetFloat();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(double &obj, rapidjson::Value &jsonValue) {
|
|
if (!jsonValue.IsNumber()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is double.";
|
|
return false;
|
|
}
|
|
obj = jsonValue.GetDouble();
|
|
return true;
|
|
}
|
|
|
|
bool JsonToObject(std::string &obj, rapidjson::Value &jsonValue) {
|
|
obj = "";
|
|
if (jsonValue.IsNull()) {
|
|
return true;
|
|
}
|
|
//object or number conver to string
|
|
else if (jsonValue.IsObject() || jsonValue.IsNumber()) {
|
|
obj = GetStringFromJsonValue(jsonValue);
|
|
} else if (!jsonValue.IsString()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is string.";
|
|
return false;
|
|
} else {
|
|
obj = jsonValue.GetString();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
template<typename TYPE> bool JsonToObject(std::vector<TYPE> &obj, rapidjson::Value &jsonValue) {
|
|
obj.clear();
|
|
if (!jsonValue.IsArray()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is std::vector<TYPE>.";
|
|
return false;
|
|
}
|
|
|
|
auto array = jsonValue.GetArray();
|
|
for (int i = 0; i < array.Size(); i++) {
|
|
TYPE item;
|
|
if (!JsonToObject(item, array[i])) {
|
|
return false;
|
|
}
|
|
obj.push_back(item);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<typename TYPE> bool JsonToObject(std::list<TYPE> &obj, rapidjson::Value &jsonValue) {
|
|
obj.clear();
|
|
if (!jsonValue.IsArray()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is std::list<TYPE>.";
|
|
return false;
|
|
}
|
|
|
|
auto array = jsonValue.GetArray();
|
|
for (int i = 0; i < static_cast<int>(array.Size()); i++) {
|
|
TYPE item;
|
|
if (!JsonToObject(item, array[i])) {
|
|
return false;
|
|
}
|
|
obj.push_back(item);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<typename TYPE> bool JsonToObject(std::map<std::string, TYPE> &obj, rapidjson::Value &jsonValue) {
|
|
obj.clear();
|
|
if (!jsonValue.IsObject()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) +
|
|
" but object is std::map<std::string, TYPE>.";
|
|
return false;
|
|
}
|
|
|
|
for (auto iter = jsonValue.MemberBegin(); iter != jsonValue.MemberEnd(); ++iter) {
|
|
auto key = (iter->name).GetString();
|
|
auto &value = jsonValue[key];
|
|
|
|
TYPE item;
|
|
if (!JsonToObject(item, value)) {
|
|
return false;
|
|
}
|
|
|
|
obj.insert(std::pair<std::string, TYPE>(key, item));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<typename TYPE> bool JsonToObject(std::unordered_map<std::string, TYPE> &obj, rapidjson::Value &jsonValue) {
|
|
obj.clear();
|
|
if (!jsonValue.IsObject()) {
|
|
m_message = "json-value is " + GetJsonValueTypeName(jsonValue) +
|
|
" but object is std::unordered_map<std::string, TYPE>.";
|
|
return false;
|
|
}
|
|
|
|
for (auto iter = jsonValue.MemberBegin(); iter != jsonValue.MemberEnd(); ++iter) {
|
|
auto key = (iter->name).GetString();
|
|
auto &value = jsonValue[key];
|
|
|
|
TYPE item;
|
|
if (!JsonToObject(item, value)) {
|
|
return false;
|
|
}
|
|
|
|
obj.insert(std::pair<std::string, TYPE>(key, item));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public:
|
|
/******************************************************
|
|
* Conver base-type : base-type to json string
|
|
* Contain: int\uint、int64_t\uint64_t、bool、float
|
|
* double、string、vector、list、map<string,XX>
|
|
*
|
|
******************************************************/
|
|
bool ObjectToJson(int &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetInt(obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(unsigned int &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetUint(obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(short &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetInt((int)obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(unsigned short &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetUint((unsigned int)obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(int64_t &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetInt64(obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(uint64_t &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetUint64(obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(bool &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetBool(obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(float &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetFloat(obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(double &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetDouble(obj);
|
|
return true;
|
|
}
|
|
|
|
bool ObjectToJson(std::string &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetString(obj.c_str(), static_cast<rapidjson::SizeType>(obj.length()), allocator);
|
|
return true;
|
|
}
|
|
|
|
template<typename TYPE>
|
|
bool ObjectToJson(std::vector<TYPE> &obj,
|
|
rapidjson::Value &jsonValue,
|
|
rapidjson::Document::AllocatorType &allocator) {
|
|
rapidjson::Value array(rapidjson::Type::kArrayType);
|
|
for (int i = 0; i < obj.size(); i++) {
|
|
rapidjson::Value item;
|
|
if (!ObjectToJson(obj[i], item, allocator)) {
|
|
return false;
|
|
}
|
|
|
|
array.PushBack(item, allocator);
|
|
}
|
|
|
|
jsonValue = array;
|
|
return true;
|
|
}
|
|
|
|
template<typename TYPE>
|
|
bool ObjectToJson(std::list<TYPE> &obj,
|
|
rapidjson::Value &jsonValue,
|
|
rapidjson::Document::AllocatorType &allocator) {
|
|
rapidjson::Value array(rapidjson::Type::kArrayType);
|
|
for (auto i = obj.begin(); i != obj.end(); i++) {
|
|
rapidjson::Value item;
|
|
if (!ObjectToJson(*i, item, allocator)) {
|
|
return false;
|
|
}
|
|
|
|
array.PushBack(item, allocator);
|
|
}
|
|
|
|
jsonValue = array;
|
|
return true;
|
|
}
|
|
|
|
template<typename TYPE>
|
|
bool ObjectToJson(std::map<std::string, TYPE> &obj,
|
|
rapidjson::Value &jsonValue,
|
|
rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetObject();
|
|
for (auto iter = obj.begin(); iter != obj.end(); ++iter) {
|
|
auto key = iter->first;
|
|
TYPE value = iter->second;
|
|
|
|
rapidjson::Value jsonitem;
|
|
if (!ObjectToJson(value, jsonitem, allocator)) {
|
|
return false;
|
|
}
|
|
|
|
rapidjson::Value jsonkey;
|
|
jsonkey.SetString(key.c_str(), key.length(), allocator);
|
|
|
|
jsonValue.AddMember(jsonkey, jsonitem, allocator);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<typename TYPE>
|
|
bool ObjectToJson(std::unordered_map<std::string, TYPE> &obj,
|
|
rapidjson::Value &jsonValue,
|
|
rapidjson::Document::AllocatorType &allocator) {
|
|
jsonValue.SetObject();
|
|
for (auto iter = obj.begin(); iter != obj.end(); ++iter) {
|
|
auto key = iter->first;
|
|
TYPE value = iter->second;
|
|
|
|
rapidjson::Value jsonitem;
|
|
if (!ObjectToJson(value, jsonitem, allocator)) {
|
|
return false;
|
|
}
|
|
|
|
rapidjson::Value jsonkey;
|
|
jsonkey.SetString(key.c_str(), key.length(), allocator);
|
|
|
|
jsonValue.AddMember(jsonkey, jsonitem, allocator);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public:
|
|
std::string m_message;
|
|
};
|
|
|
|
class JsonHelper {
|
|
public:
|
|
/**
|
|
* @brief conver json string to class | struct
|
|
* @param obj : class or struct
|
|
* @param jsonStr : json string
|
|
* @param keys : the path of the object
|
|
* @param message : printf err message when conver failed
|
|
*/
|
|
template<typename T>
|
|
static bool JsonToObject(T &obj,
|
|
const std::string &jsonStr,
|
|
const std::vector<std::string> keys = {},
|
|
std::string *message = NULL) {
|
|
//Parse json string
|
|
rapidjson::Document root;
|
|
root.Parse(jsonStr.c_str());
|
|
if (root.IsNull()) {
|
|
if (message) {
|
|
*message = "Json string can't parse.";
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//Go to the key-path
|
|
std::string path;
|
|
rapidjson::Value &value = root;
|
|
for (int i = 0; i < (int)keys.size(); i++) {
|
|
const char *find = keys[i].c_str();
|
|
if (!path.empty()) {
|
|
path += "->";
|
|
}
|
|
path += keys[i];
|
|
|
|
if (!value.IsObject() || !value.HasMember(find)) {
|
|
if (message) {
|
|
*message = "Can't parse the path [" + path + "].";
|
|
}
|
|
return false;
|
|
}
|
|
value = value[find];
|
|
}
|
|
|
|
//Conver
|
|
JsonHelperPrivate handle;
|
|
if (!handle.JsonToObject(obj, value)) {
|
|
if (message) {
|
|
*message = handle.m_message;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief conver json string to class | struct
|
|
* @param jsonStr : json string
|
|
* @param defaultT : default value
|
|
* @param keys : the path of the object
|
|
* @param message : printf err message when conver failed
|
|
*/
|
|
template<typename T>
|
|
static T Get(const std::string &jsonStr,
|
|
T defaultT,
|
|
const std::vector<std::string> keys = {},
|
|
std::string *message = NULL) {
|
|
T obj;
|
|
if (JsonToObject(obj, jsonStr, keys, message)) {
|
|
return obj;
|
|
}
|
|
|
|
return defaultT;
|
|
}
|
|
|
|
/**
|
|
* @brief conver class | struct to json string
|
|
* @param errMessage : printf err message when conver failed
|
|
* @param isPretty Output pretty format json string
|
|
* @param obj : class or struct
|
|
* @param jsonStr : json string
|
|
*/
|
|
template<typename T> static bool ObjectToJson(T &obj, std::string &jsonStr, bool isPretty, std::string *message) {
|
|
rapidjson::Document root;
|
|
root.SetObject();
|
|
rapidjson::Document::AllocatorType &allocator = root.GetAllocator();
|
|
|
|
//Conver
|
|
JsonHelperPrivate handle;
|
|
if (!handle.ObjectToJson(obj, root, allocator)) {
|
|
if (message) {
|
|
*message = handle.m_message;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
jsonStr = handle.GetStringFromJsonValue(root, isPretty);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @brief conver class | struct to json string
|
|
* @param errMessage : printf err message when conver failed
|
|
* @param obj : class or struct
|
|
* @param isPretty Output pretty format json string
|
|
* @param jsonStr : json string
|
|
*/
|
|
template<typename T> static bool ObjectToJson(T &obj, std::string &jsonStr, bool isPretty = false) {
|
|
rapidjson::Document root;
|
|
root.SetObject();
|
|
rapidjson::Document::AllocatorType &allocator = root.GetAllocator();
|
|
|
|
//Conver
|
|
JsonHelperPrivate handle;
|
|
if (!handle.ObjectToJson(obj, root, allocator)) {
|
|
return false;
|
|
}
|
|
|
|
jsonStr = handle.GetStringFromJsonValue(root, isPretty);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace aigc
|