您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關C++中類結構體與json如何相互轉換的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
之前寫C#的時候,解析json
字符串一般使用的是開源的類庫Newtonsoft.Json
,方法十分簡潔,比如:
class Project { public string Input { get; set; } public string Output { get; set; } } JavaScriptSerializer serializer = new JavaScriptSerializer(); Project test = serializer.Deserialize<Project>(@"{"Input":"1","Output":"2"}");
一行代碼就能將json字符串轉為相應的類對象。
最近寫C++需要處理一下json
數據,于是上github
找了很多很強大的開源庫,像jsoncpp
、rapidjson
、json
,基本上都滿足了開發需求,但想要做成像寫C#那樣子就要做二次開發。于是有了自己寫一個簡單的json轉類 | 結構體的工具的想法(開源地址)。
需求如下:
只有頭文件,方便使用
最多三行代碼解決轉換
支持類|結構體 與 json
的相互轉換
支持多種基本數據類型,如int
、float
、string
、bool
等
支持STL基本類型,如vector
、list
、map<string
,T>等
支持嵌套關系
支持成員重命名,比方說json
中的關鍵字是name
,成員命名可寫成Name或其他。
class Student { public: string Name; int Age; AIGC_JSON_HELPER(Name, Age)//成員注冊 AIGC_JSON_HELPER_RENAME("name","age")//成員重命名,不需要可以刪除這條 }; int main() { //json轉類對象 Student person; JsonHelper::JsonToObject(person, R"({"name":"XiaoMing", "age":15})"); //類對象轉json string jsonStr; JsonHelper::ObjectToJson(person, jsonStr); return 0; }
因為剛好rapidjson
只需要頭文件就可以使用,所以選擇了rapidjson
作為基礎庫,進行二次開發。
作為最底層的接口,只需要進行一個賦值的操作即可,后續如果想要增加一些其他類型支持,添加起來也比較方便。
static bool JsonToObject(int &obj, rapidjson::Value &jsonValue) { if (jsonValue.IsNull() || !jsonValue.IsInt()) return false; obj = jsonValue.GetInt(); return true; } static bool JsonToObject(unsigned int &obj, rapidjson::Value &jsonValue) { if (jsonValue.IsNull() || !jsonValue.IsUint()) return false; obj = jsonValue.GetUint(); return true; } static bool JsonToObject(int64_t &obj, rapidjson::Value &jsonValue) { if (jsonValue.IsNull() || !jsonValue.IsInt64()) return false; obj = jsonValue.GetInt64(); return true; } //其他類型... ...
這里使用宏定義方式 + 可變參數模板的方式來實現,即可依次對注冊的成員進行賦值
template <typename TYPE, typename... TYPES> static bool WriteMembers(std::vector<std::string> &names, int index, rapidjson::Value &jsonValue, TYPE &arg, TYPES &... args) { if (!WriteMembers(names, index, jsonValue, arg)) return false; return WriteMembers(names, ++index, jsonValue, args...); } template <typename TYPE> static bool WriteMembers(std::vector<std::string> &names, int index, rapidjson::Value &jsonValue, TYPE &arg) { const char *key = names[index].c_str(); if (!jsonValue.HasMember(key)) return true; if (!JsonToObject(arg, jsonValue[key])) return false; return true; } #define AIGC_JSON_HELPER(...) \ bool AIGC_CONVER_JSON_TO_OBJECT(rapidjson::Value &jsonValue, std::vector<std::string> &names) \ { \ if (names.size() <= 0) \ names = aigc::JsonHelper::GetMembersNames(#__VA_ARGS__); \ return aigc::JsonHelper::WriteMembers(names, 0, jsonValue, __VA_ARGS__); \ }
自定義類由于并不清楚外界使用時,是否有按規定添加好成員注冊接口,所以這里采用enable_if
的方式來嘗試調用,編譯的時候也就不會報錯。
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::AIGC_CONVER_JSON_TO_OBJECT)); template <typename TT> static int func(...); const static bool has = (sizeof(func<T>(NULL)) == sizeof(char)); }; template <typename T, typename enable_if<HasConverFunction<T>::has, int>::type = 0> static inline bool JsonToObject(T &obj, rapidjson::Value &jsonValue) { std::vector<std::string> names = LoadRenameArray(obj); return obj.AIGC_CONVER_JSON_TO_OBJECT(jsonValue, names); } template <typename T, typename enable_if<!HasConverFunction<T>::has, int>::type = 0> static inline bool JsonToObject(T &obj, rapidjson::Value &jsonValue) { return false; }
/** * @brief conver json string to class | struct * @param obj : class or struct * @param jsonStr : json string */ template <typename T> static inline bool JsonToObject(T &obj, const std::string &jsonStr) { rapidjson::Document root; root.Parse(jsonStr.c_str()); if (root.IsNull()) return false; return JsonToObject(obj, root); }
最核心的部分也就上面的幾個模塊,其他的都是一些瑣碎的增加類型支持等操作。
感謝各位的閱讀!關于“C++中類結構體與json如何相互轉換”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。