C++解析和构建json【cjson使用手册】
- 一、cjson下载
- 二、cjson工程使用
- 2.1 静态库使用
- 2.1 源码使用(推荐)
 
- 三、cjson详解
- 3.1 解析json字符串
- 3.1.1 解析对象
- 3.1.2 解析数组:方法一(获取列表数量然后按照位置获取)
- 3.1.2 解析数组:方法二(使用foreach遍历)
- 3.1.3 解析对象包含数组
- 3.1.4 解析数组对象
 
- 3.2 json结构体构建
- 3.2.1 构建对象
- 3.2.2 构建数组
- 3.2.3 构建对象中包含数组
- 3.2.4 构建数组中包含对象
 
- 3.3 json类型判断
- 1. `cJSON_IsInvalid`
- 2. `cJSON_IsFalse`
- 3. `cJSON_IsTrue`
- 4. `cJSON_IsBool`
- 5. `cJSON_IsNull`
- 6. `cJSON_IsNumber`
- 7. `cJSON_IsString`
- 8. `cJSON_IsArray`
- 9. `cJSON_IsObject`
- 10. `cJSON_IsRaw`
 
 
- 四、源码地址
一、cjson下载
-  国外:github下载 
 https://github.com/DaveGamble/cJSON
  
-  国内:gicode下载 
 https://gitcode.com/gh_mirrors/cj/cJSON/overview
  
二、cjson工程使用
2.1 静态库使用
将cjson作为静态库使用。
- 1.构建cjson静态库
 构建静态库就是将cjson作为静态库使用,其实和源码使用没有太大的区别。
 构建CMakeLists.txt
cmake_minimum_required( VERSION 3.10 )
project(cjson)
add_library(${PROJECT_NAME} cjson.c cjson.h)
install(TARGETS ${PROJECT_NAME}  DESTINATION lib)
install(FILES ${PROJECT_SOURCE_DIR}/cjson.h DESTINATION include)
使用qt编译。
- 2.使用cjson静态库
 将编译的cjson.lib和cjson.h放在项目中的depend/cjson/中
 depend/cjson/lib/cjson.lib
 depend/cjson/include/cjson.h
 项目中指定库文件和头文件。分别任上面两个目录就可以了。
2.1 源码使用(推荐)
源码使用,比较简单。
 直接将cjson.c和cjson.h放在源文件中一起编译就可以了。
三、cjson详解
3.1 解析json字符串
json解析的最终结果只有三种1. 字符串类型。2.整数。3.float。
 整个字符串解析的关键函数为cJSON_Parse
 公共函数说明
 文件读取,传递文件名称获取文件内容。(因为json文件中的双引号比较麻烦输入,所以我直接将测试内容放在文件中读取这样比较方便。)
string ReadFile(string filePath){
    ifstream ifs(filePath);
    if(!ifs.is_open()){
        return "";
    }
    std::string line;
    std::string content;
    while (getline(ifs, line)) { // 逐行读取文件内容
        content+=line;
    }
    ifs.close(); // 关闭文件
    return content;
}
因为创建的对象不知道什么时候释放,因此我使用智能指针的方式,等到他不使用的时候自动释放。
struct cJSON_Deleter {
    void operator()(cJSON* json) const {
        cJSON_free(json);
    }
};
3.1.1 解析对象
样例一:
{
	"name":"三雷科技",
	"age":100,
	"hight":124.5
}
解析代码如下:
void parse_object1(){
    string content = ReadFile("data/object1.txt");
    if(content.empty()){
        return;
    }
    std::unique_ptr<cJSON,cJSON_Deleter> json_data(cJSON_Parse(content.c_str()));
    if(json_data == nullptr){
        cout <<"解析失败!";
    }
    cJSON *json_name = cJSON_GetObjectItem(json_data.get(),"name");
    cJSON *json_age = cJSON_GetObjectItem(json_data.get(),"age");
    cJSON *json_hight = cJSON_GetObjectItem(json_data.get(),"hight");
    string name = json_name->valuestring;
    int age = json_age->valueint;
    double hight = json_hight->valuedouble;
    cout <<"name:"<<name<<endl;
    cout <<"age:"<<age<<endl;
    cout <<"hight:"<<hight<<endl;
}
json_data:为获取的json对象。
 cJSON_GetObjectItem从对象中获取对象中的属性内容。根据关键词进行获取。
 拿到该关键的json对象item以后再使用valuestring\valueint\valuedouble获取对应类型的值。
3.1.2 解析数组:方法一(获取列表数量然后按照位置获取)
样例一:
["apple","banana","Orange","watermelon"]
想获取列表的长度,然后按照位置进行获取。
 cJSON_GetArraySize:该函数用于获取 JSON 数组的大小(即数组中的元素数量)。
 cJSON_GetArrayItem:该函数用于获取 JSON 数组中的某个特定索引处的元素。
void parse_array1(){
    string content = ReadFile("data/array1.txt");
    if(content.empty()){
        cout<<"读取内容失败";
        return;
    }
    std::unique_ptr<cJSON,cJSON_Deleter> json_data(cJSON_Parse(content.c_str()));
    int len = cJSON_GetArraySize(json_data.get());
    for(int i = 0 ;i < len ; i++){
       cJSON *item = cJSON_GetArrayItem(json_data.get(),i);
        if(item){
           cout <<"item:"<<item->valuestring<<endl;
        }
     }
}
3.1.2 解析数组:方法二(使用foreach遍历)
样例一:
["apple","banana","Orange","watermelon"]
cJSON_ArrayForEach:遍历 cJSON 数组: cJSON_ArrayForEach 可以轻松遍历 cJSON 数组中的每一个元素,省去了手动获取数组大小和逐个索引访问元素的麻烦。
void parse_array2(){
    string content = ReadFile("data/array1.txt");
    if(content.empty()){
        cout<<"读取内容失败";
        return;
    }
    std::unique_ptr<cJSON,cJSON_Deleter> json_data(cJSON_Parse(content.c_str()));
    cJSON* item = nullptr;
    cJSON_ArrayForEach(item, json_data.get()) {
        if (cJSON_IsString(item)) {
            std::cout << "item: " << item->valuestring<< std::endl;
        }
    }
}
3.1.3 解析对象包含数组
案例:
{
	"fruit":["apple","banana","Orange","watermelon"],
	"unit":["one","two","three"]
}
需要分布解析,先解析对象然后在解析每个数组,需要一个一个的解析。
void parse_object_array(){
    string content = ReadFile("data/object_array.txt");
    if(content.empty()){
        cout<<"读取内容失败";
        return;
    }
    std::unique_ptr<cJSON,cJSON_Deleter> json_data(cJSON_Parse(content.c_str()));
    cJSON *json_fruit_array = cJSON_GetObjectItem(json_data.get(),"fruit");
   cJSON* item = nullptr;
    cJSON_ArrayForEach(item, json_fruit_array) {
        if (cJSON_IsString(item)) {
            std::cout << "fruit item: " << item->valuestring<< std::endl;
        }
    }
    cJSON *json_unit_array = cJSON_GetObjectItem(json_data.get(),"unit");
    cJSON_ArrayForEach(item, json_unit_array) {
        if (cJSON_IsString(item)) {
            std::cout << "unit item: " << item->valuestring<< std::endl;
        }
    }
}
运行结果
 
3.1.4 解析数组对象
案例 array_object.txt
{
        "students": [
            {"name": "Alice", "age": 21},
            {"name": "Bob", "age": 22},
            {"name": "Charlie", "age": 23}
        ]
}
void parse_array_object(){
    string content = ReadFile("data/array_object.txt");
    if(content.empty()){
        cout<<"读取内容失败";
        return;
    }
     std::unique_ptr<cJSON,cJSON_Deleter> json_data(cJSON_Parse(content.c_str()));
     // 先获取students的json
     cJSON *json_student_array = cJSON_GetObjectItem(json_data.get(),"students");
     if(cJSON_IsNull( json_student_array)){
         cout<<"students 解析失败";
         return ;
     }
     if(cJSON_IsArray(json_student_array)){
         cJSON* item = nullptr;
         cJSON_ArrayForEach(item,json_student_array){
             cJSON* json_item_name = cJSON_GetObjectItem(item,"name");
             cJSON* json_item_age = cJSON_GetObjectItem(item,"age");
             if(json_item_name){
                 std::cout <<"name:"<<json_item_name->valuestring;
             }
             if(json_item_age){
                 std::cout <<",age:"<<json_item_age->valueint;
             }
             std::cout << std::endl;
         }
     }
}
运行结果
 
3.2 json结构体构建
构建好的json结构体可以通过cJSON_Print获取json结构对应的字符串。
3.2.1 构建对象
3.2.2 构建数组
- 构建整形数组
 cJSON_CreateIntArray:
void CreateIntArray(){
	int num[] = {10,4,5,6,1};
	cJSON *json_int_array = cJSON_CreateIntArray(num,sizeof(num));
	std::cout << cJSON_Print(json_int_array)<<std::endl;;
	cJSON_Delete(json_int_array );
}

- 构建float数组
 cJSON_CreateFloatArray:
void CreateFloatArray(){
	float num[] = {10.1,4.2,5.3,6.4,1.5};
	cJSON *json_float_array = cJSON_CreateFloatArray(num,sizeof(num));
	std::cout << cJSON_Print(json_float_array)<<std::endl;;
	cJSON_Delete(json_float_array );
}

- 构建Double数组
 cJSON_CreateDoubleArray:
void CreateDoubleArray(){
	double num[] = {10.1,4.2,5.3,6.4,1.5};
	cJSON *json_float_array = cJSON_CreateDoubleArray(num,sizeof(num));
    std::cout << cJSON_Print(json_float_array)<<std::endl;;
	cJSON_Delete(json_float_array );
}

- 构建字符串数组
 cJSON_CreateStringArray:
void CreateDoubleArray(){
	const char *string[] = {    "Hello",    "World",    "I",    "Am",    "Programmer"};
	cJSON *json_string_array = cJSON_CreateDoubleArray(string,sizeof(string)/sizeof(string[0]));
	std::cout << cJSON_Print(json_string_array)<<std::endl;;
	cJSON_Delete(json_string_array);
}

- 构建任意类型数组
void CreateArray(){
    cJSON *cjson_array = cJSON_CreateArray();
    cJSON *cjson_number = cJSON_CreateNumber(10);
    cJSON *cjson_bool = cJSON_CreateBool(false);
    cJSON *cjson_string = cJSON_CreateString("name");
    cJSON_AddItemToArray(cjson_array,cjson_number);
    cJSON_AddItemToArray(cjson_array,cjson_bool );
    cJSON_AddItemToArray(cjson_array,cjson_string );
    std::cout <<cJSON_Print(json_array)<<std::endl;
     cJSON_Delete(cjson_array);
}
3.2.3 构建对象中包含数组
void CreateObejectArray(){
    std::unique_ptr<cJSON,cJSON_Deleter> json_data(cJSON_CreateObject());
    const  char *string[] = {    "Hello",    "World",    "I",    "Am",    "Programmer"};
    cJSON *json_string_array = cJSON_CreateStringArray(string,sizeof(string)/sizeof(string[0]));
    double num[] = {10.1,4.2,5.3,6.4,1.5};
    cJSON *json_float_array = cJSON_CreateDoubleArray(num,sizeof(num)/sizeof (double));
    cJSON_AddItemToObject(json_data.get(),"word",json_string_array );
    cJSON_AddItemToObject(json_data.get(),"number",json_float_array );
    std::cout  <<cJSON_Print(json_data.get())<<std::endl;
}
cJSON_AddItemToObeject:创建一个item添加到一个对象中,参数为:
 json_object:json对象
 string : 关键词
 json_item:对象的值
 
3.2.4 构建数组中包含对象
struct Student{
    Student(std::string name ,int age ,std::string sex){
        this->name = name;
        this->age = age;
        this->sex = sex;
    }
    std::string name;
    int age;
    std::string sex;
};
void CreateArrayObeject(){
    std::unique_ptr<cJSON,cJSON_Deleter> json_data(cJSON_CreateArray());
    std::vector<Student> vstu;
    Student stu1("zhangsan",10,"nan");
    Student stu2("lisi",12,"nan");
    Student stu3("wangwu",13,"nv");
    vstu.push_back(stu1);
    vstu.push_back(stu2);
    vstu.push_back(stu3);
    for(auto stu :vstu){
        cJSON *item = cJSON_CreateObject();
        cJSON_AddItemToObject(item ,"name",cJSON_CreateString(stu.name.c_str()));
        cJSON_AddItemToObject(item ,"age",cJSON_CreateNumber(stu.age));
        cJSON_AddItemToObject(item ,"sex",cJSON_CreateString(stu.sex.c_str()));
        cJSON_AddItemToArray(json_data.get(),item);
    }
    std::cout  <<cJSON_Print(json_data.get())<<std::endl;
}
运行结果:
 
3.3 json类型判断
cJSON 库提供了一组宏,用于检查 cJSON 对象的类型。这些宏使得在处理 JSON 数据时,可以轻松地判断 JSON 对象的类型,并根据类型进行相应的处理。以下是这些宏的详细说明:
1. cJSON_IsInvalid
 
功能: 判断 cJSON 对象是否是无效的(类型为 cJSON_Invalid)。
 使用场景: 在处理 JSON 解析结果时,用于检查对象是否无效或未初始化。
2. cJSON_IsFalse
 
功能: 判断 cJSON 对象是否为布尔值 false(即类型为 cJSON_False)。
 使用场景: 用于检测 JSON 布尔值 false。
3. cJSON_IsTrue
 
功能: 判断 cJSON 对象是否为布尔值 true(即类型为 cJSON_True)。
 使用场景: 用于检测 JSON 布尔值 true。
4. cJSON_IsBool
 
功能: 判断 cJSON 对象是否为布尔类型(即类型为 cJSON_True 或 cJSON_False)。
 使用场景: 用于检测 JSON 布尔类型的值,不论是 true 还是 false。
5. cJSON_IsNull
 
功能: 判断 cJSON 对象是否为 null(即类型为 cJSON_NULL)。
 使用场景: 用于检测 JSON 中的 null 值。
6. cJSON_IsNumber
 
功能: 判断 cJSON 对象是否为数字(即类型为 cJSON_Number)。
 使用场景: 用于检测 JSON 中的数字类型。
7. cJSON_IsString
 
功能: 判断 cJSON 对象是否为字符串(即类型为 cJSON_String)。
 使用场景: 用于检测 JSON 中的字符串类型。
8. cJSON_IsArray
 
功能: 判断 cJSON 对象是否为数组(即类型为 cJSON_Array)。
 使用场景: 用于检测 JSON 中的数组类型。
9. cJSON_IsObject
 
功能: 判断 cJSON 对象是否为对象(即类型为 cJSON_Object)。
 使用场景: 用于检测 JSON 中的对象类型。
10. cJSON_IsRaw
 
功能: 判断 cJSON 对象是否为原始未处理的 JSON 数据(即类型为 cJSON_Raw)。
 使用场景: 用于检测未被处理的原始 JSON 数据,通常用在需要处理 JSON 内嵌代码或未解析的文本时。
四、源码地址
git源码
 https://gitcode.net/arv002/qt/-/tree/master/c%2B%2B/cjson
 csdn源码
https://download.csdn.net/download/arv002/89633210


















