NetTunnelWindows/NetTunnelSDK/AIGCJson.hpp

1052 lines
34 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>
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 = names.size(); i < (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 = names.size(); i < (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)
{
rapidjson::StringBuffer buffer;
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 (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(), 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 = atof(value.c_str());
}
void StringToObject(double &obj, std::string &value)
{
obj = atof(value.c_str());
}
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 < 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(), 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 obj : class or struct
* @param jsonStr : json string
*/
template <typename T>
static bool ObjectToJson(T &obj, std::string &jsonStr, std::string *message = NULL)
{
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);
return true;
}
};
} // namespace aigc