NetTunnelWindows/NetTunnelSDK/include/AIGCJson.hpp

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 (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