c/c++使用cJson解析未知内容的json字符串

关于json我这里就不做缀饰,这里给出链接百度百科json
我这里只介绍下json中的符号格式
① { } : 双括号表示一个json对象。例如:{"name":"ljl"},这代表一个name为ljl的对象
②[ ] : 中括号表示数组。例如:[{"name","ljl"},{"memory","ljx"}],表示包含两个对象的数组
③ : :冒号表示后者是前者的值。比如我上面的{"name":"ljl"},ljl是name的值
④" " :双引号内是属性或值。例如{"date","18-09-28"},属性是date,它的值是18-09-28
⑤, :逗号表示间隔,常用于两个对象之间。如[{"name","ljl"},{"memory","ljx"}]
json在java中使用比较容易,一般在c/c++中不使用该格式,但有时项目会涉及到前端用c/c++去编写而后端用Java编写,这两者间通信时一般都选用Json格式
c/c++中能够解析、创建Json字串的工具(或者说方法)不多,目前笔者只找到cJson跟Jsoncpp两种简单方法。其中cJson最为方便,这里使用cJson做为解析、创建Json的工具
如果没有cJson,本文给出下载链接cJson下载
将cJson.h和cJson.c添加到项目并包含路径即可使用(注意:.c文件必须添加至项目,否则不会编译)
test.c文件为官方演示测试文件,里面有一些函数的简单用法
下面展示下如何解析已知结构的简单Json字串
#include <iostream>
#include "cJSON.h"
#include <string>
#include <Windows.h>
#include <map>
using namespace std;
int main()
{
string json_string = "{\"ResCode\":\"000\",\"ResDesc\":\"业务受理成功\",\"ServiceResMsg\":\"这是XML格式字串\"}";
//JSON字符串到cJSON格式
cJSON* cjson1 = cJSON_Parse(json_string.c_str());
//判断cJSON_Parse函数返回值确定是否打包成功
if(cjson1 == NULL)
{
printf("json pack into cjson error...");
}
else
{
//打包成功调用cJSON_Print打印输出
cJSON_Print(cjson1); // 将json形式打印成正常字符串形式
}
//获取字段值
//cJSON_GetObjectltem返回的是一个cJSON结构体所以我们可以通过函数返回结构体的方式选择返回类型!
string _1_string = cJSON_GetObjectItem(cjson1,"ResCode")->valuestring;
string _2_string = cJSON_GetObjectItem(cjson1,"ResDesc")->valuestring;
string _3_string = cJSON_GetObjectItem(cjson1,"ServiceResMsg")->valuestring;
cout << _1_string << endl;
cout << _2_string << endl;
cout << _3_string << endl;
//delete cjson
cJSON_Delete(cjson1);
return 0;
}
代码中
string _1_string = cJSON_GetObjectItem(cjson1,"ResCode")->valuestring;
string _2_string = cJSON_GetObjectItem(cjson1,"ResDesc")->valuestring;
string _3_string = cJSON_GetObjectItem(cjson1,"ServiceResMsg")->valuestring;
通过调用cJSON_GetObjectItem函数将已知结构,比如ResCode,ResDesc,ServiceResMsg三个节点的值读出来
关于复杂的Json字串解析,诸如包含数组的,可以去其他csdn查看,有些博客写的还是很到位的,我这里主要讲解析未知内容的Json字串
笔者研究了下cJson.c跟cJson.h文件,貌似没有发现可以直接解析未知Json字串的方法,但笔者在cJson.h中找到了官方定义的结构体
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;
笔者稍微研究了下cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)函数
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string)
{
cJSON *c=object->child;
while (c && cJSON_strcasecmp(c->string,string))
c=c->next;
return c;
}
该函数内部实现的是通过遍历cJson的对象中struct cJSON *child中的struct cJSON *next,*prev来达成遍历Json字串的目的
下面我们就通过这种方法自己写一个接口函数,实现解析未知结构、内容的Json字串
#include <iostream>
#include "cJSON.h"
#include <string>
#include <Windows.h>
#include <map>
using namespace std;
map<string,string> MapAnalysisJSON(string ResMessage)
{
map<string,string> mapResMessage;
cJSON* cjson = cJSON_Parse(ResMessage.c_str());
if(cjson == NULL)
{
printf("json pack into cjson error...");
}
else
{
cJSON_Print(cjson);
}
cJSON * c = cjson->child;
while (c)
{
mapResMessage.insert(pair<string,string>(c->string,c->valuestring));
c = c->next;
}
c = NULL;
return mapResMessage;
}
int main()
{
string json_string = "{\"ResCode\":\"000\",\"ResDesc\":\"业务受理成功\",\"ServiceResMsg\":\"这是XML格式字串\"}";
map<string,string> recmap;
recmap = MapAnalysisJSON(json_string);
if (recmap.size() == 0)
{
cout << "recmap is empty!";
}
for (map<string,string>::iterator iter = recmap.begin();iter != recmap.end();iter++)
{
cout << iter->first << " " << iter->second << endl;
}
return 0;
}
我这里将未知Json字串解析成map对象
map跟Json的理念有点相似即一个键对应一个值,当然你也可以将Json解析成你想要的任何格式




更多推荐
所有评论(0)