C++轻量级Json解析工具—TinyJson
C++輕量級Json解析工具—TinyJson
簡介
之前Json解析工具習慣于用**nlohmann/json**,后來發現要兼容Centos5系的系統,且需要批量使用,系統升級gcc/g++升級有點不現實,后來改用輕量級TinyJson庫,說一下在使用碰到的一些問題以及為了兼容性作出的修改。
TinyJson輕量級json解析工具,只需要包含頭就可以直接使用。兼容Windows/Linux平臺。Mac并沒有進行相關測試。理論上兼容。
TinyJson相關信息
Git地址:https://github.com/button-chen/tinyjson
相關介紹,在github并沒有過的介紹,但是在百度的時候發現了很多關于TinyJson的介紹,有點亂,不一一細究了。
- 使用樣例
在github中有相關的一些介紹,不做詳細介紹。
測試缺陷
1.兼容C++03 編譯
Lamba表達式的去除
char LastValidChar(std::string json,int index) {for (int i = index - 1; i >= 0; --i) {if (isspace(json[i])) continue;char tmp = json[i];return tmp;}return '\0'; } //-------------------------------------------------------------// //將下方的lamba表達式注釋掉,并改為添加上的函數// // 解析為 key-value 調用一次解析一個層次 inline bool ParseJson::ParseObj(std::string json) {//------注釋區域--------------//auto LastValidChar = [&](int index)->char{for (int i = index-1; i >= 0; --i){if (isspace(json[i])) continue;char tmp = json[i];return tmp;}return '\0';};//---------------------------// else if (isdigit(nextc) && LastValidChar(json,i) == ':') //-----------------修改----------------------------// //---LastValidChar(i) --LastValidChar(json,i)-----// else if (isdigit(nextc) && LastValidChar(i) == ':') {tokens = FetchNumStr(json, i, offset); }2.不支持數組的讀取
測試demo
std::string data = "{\"type\": \"cdk\",\"cdk\":\"18000002\",\ \"frist_reward_goods\":[\ [\"1\",\"3037\",\"100\"],\ [\"2\",\"3037\",\"100\"],\ [\"3\",\"3037\",\"100\"],\ [\"4\",\"3037\",\"100\"]]}";TinyJson在讀取的時候,數組只顯示為字符串,無論 tiny::xarray還是 tiny::xobject 都無法解析。后來就做了修改。
tiny::xarray arry; get_value(j, std::string("frist_reward_goods"), arry);結果如下圖:
根據讀取結果,處理結果無法使用。數組元素讀取結果,把[]符號都加入進去還是讀取很失敗。
修改如下:
/* 函數名:字符串切割子函數 srcStr:源字符串 delimStr:分割符字符串 repeatedCharIgnored:是否支持分割符字符串合并 return:切割后的字符串Vector */ std::vector<std::string> splitString(std::string srcStr, std::string delimStr, bool repeatedCharIgnored) {std::vector<std::string> resultStringVector;std::replace_if(srcStr.begin(), srcStr.end(), [&](const char& c) {if (delimStr.find(c) != std::string::npos) { return true; } else { return false; }}/*pred*/, delimStr.at(0));//將出現的所有分隔符都替換成為一個相同的字符(分隔符字符串的第一個)size_t pos = srcStr.find(delimStr.at(0));std::string addedString = "";while (pos != std::string::npos) {addedString = srcStr.substr(0, pos);if (!addedString.empty() || !repeatedCharIgnored) {resultStringVector.push_back(addedString);}srcStr.erase(srcStr.begin(), srcStr.begin() + pos + 1);pos = srcStr.find(delimStr.at(0));}addedString = srcStr;if (!addedString.empty() || !repeatedCharIgnored) {resultStringVector.push_back(addedString);}return resultStringVector; } /* 字符串數組獲取 in j:Json對象 int key:Json鍵值 output value 字符串數組 --利用 key,獲取數組字符串。'['數組元素的開始,'],'為一個字符串數組的結束。判斷'],'來劃分數組。內部以','來劃分,子相元素。 */ static void get_value(tiny::TinyJson j, std::string key, std::vector<std::vector<std::string>> &value){std::string object = j.Get<std::string>(key);int i = 1;while ( i < object.length() - 1){std::vector<std::string> item;if (object[i] == '['){std::string item_string;i++;while (object[i] != ']' && object[i] != '['){if (object[i] != ',' && object[i] != '"' && object[i] != ' '){item_string += object[i];}else if (object[i] == ',' || ( object[i] == '"'&& object[i+1] == ']')){item.push_back(item_string);item_string = "";}i++;}}if(!item.empty())value.push_back(item);i++;}}處理結果如下所示:
std::vector<std::vector<std::string>> vec; get_value(j, std::string("frist_reward_goods"), vec);3.相連Key和value的獲取
在實際使用中,發現相連的key和value如果相同,返回的value為下一個key值。
demo:type的值為cdk,cdk的值為18000002
"type\": \"cdk\",\"cdk\":\"18000002\" std::string cdk; get_value(j,std::string("cdk"),cdk);處理結果如下圖:
原因:
原處理函數為:
template<typename R> R Get(std::string key, R defVal) {auto itr = std::find(KeyVal_.begin(), KeyVal_.end(), key);if (itr == KeyVal_.end()) {return defVal;}return Value(*(++itr)).GetAs<R>(); }使用了std::find()方法,find的定義為返回第一個找到的元素。這里并沒有做返回的值是否為key還是value,所以出現了這個錯誤,修改如下,或元素的類型判斷。根據json key和value一一對應的關系,可以判斷value為偶數為,從0開始計數,value為奇數位。所以修改如下,手動遍歷。
template<typename R> R Get(std::string key, R defVal) {auto itr = KeyVal_.begin();int i = 0;for (itr; itr != KeyVal_.end(); itr++){if (key == (*itr) && !(i % 2))break;i++;}if (itr == KeyVal_.end()) {return defVal;}return Value(*(++itr)).GetAs<R>(); }運行結果如下:
cdk:18000002封裝
頭文件調用
#include <iostream> #include <string> #include <vector> #include "tinyjson.hpp" //類的封裝 class Json { public:static tiny::TinyJson parse(std::string data){tiny::TinyJson json;json.ReadJson(data);return json;}static void get_value(tiny::TinyJson j, std::string key, std::string &value){value = j.Get<std::string>(key);}static void get_value(tiny::TinyJson j, std::string key, tiny::xarray &value){value = j.Get<tiny::xarray>(key);}static void get_value(tiny::TinyJson j, std::string key, std::vector<std::vector<std::string>> &value){std::string object = j.Get<std::string>(key);int i = 1;while ( i < object.length() - 1){std::vector<std::string> item;if (object[i] == '['){std::string item_string;i++;while (object[i] != ']' && object[i] != '['){if (object[i] != ',' && object[i] != '"' && object[i] != ' '){item_string += object[i];}else if (object[i] == ',' || ( object[i] == '"'&& object[i+1] == ']')){item.push_back(item_string);item_string = "";}i++;}}if(!item.empty())value.push_back(item);i++;}} private: };模版函數
template<typename R> void get_value(tiny::TinyJson j, std::string key, R &value) {Json::get_value(j, key, value); }使用:
//序列化 tiny::TinyJson j = Json::parse(data); //普通元素 std::string cdk; get_value(j,std::string("cdk"),cdk); //list數組元素 tiny::xarray arry; get_value(j, std::string("frist_reward_goods"), arry); //vector數組元素 std::vector<std::vector<std::string>> vec; get_value(j, std::string("frist_reward_goods"), vec);其他
對TinyJson的再次封裝,使使用足夠方便。因為本人只使用解析,所以針對修改是針對TinyJson的解析修改。其他還需要其他人完善。
也可以將我上訴的元素再次封裝于tinyjson.hpp.獲取根據其他的使用再次封裝。
想著上傳合并到原作者的git分支,但是已經有兩年沒有更新就沒有做。
如需源碼請留言。
總結
以上是生活随笔為你收集整理的C++轻量级Json解析工具—TinyJson的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WPF中的动画——(四)缓动函数
- 下一篇: mysql addslashes_PHP