json解析工具

您所在的位置:网站首页 查看json的软件 json解析工具

json解析工具

#json解析工具| 来源: 网络整理| 查看: 265

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 splitString(std::string srcStr, std::string delimStr, bool repeatedCharIgnored) { std::vector 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 &value) { std::string object = j.Get(key); int i = 1; while ( i < object.length() - 1) { std::vector 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 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 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(); }

使用了std::find()方法,find的定义为返回第一个找到的元素。这里并没有做返回的值是否为key还是value,所以出现了这个错误,修改如下,或元素的类型判断。根据json key和value一一对应的关系,可以判断value为偶数为,从0开始计数,value为奇数位。所以修改如下,手动遍历。

template 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(); }

运行结果如下:

cdk:18000002 封装

头文件调用

#include #include #include #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(key); } static void get_value(tiny::TinyJson j, std::string key, tiny::xarray &value) { value = j.Get(key); } static void get_value(tiny::TinyJson j, std::string key, std::vector &value) { std::string object = j.Get(key); int i = 1; while ( i < object.length() - 1) { std::vector 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 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 vec; get_value(j, std::string("frist_reward_goods"), vec); 其他

对TinyJson的再次封装,使使用足够方便。因为本人只使用解析,所以针对修改是针对TinyJson的解析修改。其他还需要其他人完善。

也可以将我上诉的元素再次封装于tinyjson.hpp.获取根据其他的使用再次封装。

想着上传合并到原作者的git分支,但是已经有两年没有更新就没有做。

如需源码请留言。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3