当前位置:   article > 正文

C语言:解析cjson详解释

cjson

一、json是什么

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。-- 来自百度百科

二、 json介绍

1.下载cJSON库文件
cJSON库文件一共两个文件:cJSON.h和cJSON.c。下载地址

2.语法
数据在名称/值对中,key : value
JSON key 必须是字符串
数据由逗号分隔
大括号 {} 保存对象
中括号 [] 保存数组,数组可以包含多个对象

3.JSON value 值
JSON 值可以是:字符串, 数字, 对象, 数组, 布尔值或 null

数字(整数或浮点数)
JSON 数字可以是整型或者浮点型:
{ “age”:30 }

字符串(在双引号中)
{ “name”:“danxia”}

逻辑值(true 或 false)
JSON 布尔值可以是 true 或者 false:
{ “flag”:true }

数组(在中括号[]中)
数组值必须是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null)。
如:
{
“name”:“danxia”,
“age”:18,
“sites”:[ “Google”, “baidu”, “google” ]
}

数组可包含多个对象:
{
“sites”: [
{ “name”:“danxia” , “url”:“www.Google.com” },
{ “name”:“meixia” , “url”:“www.baidu.com” },
{ “name”:“meidi” , “url”:“www.google.com” }
]
}

对象(在大括号{}中)
JSON 对象使用在大括号({})中书写。
对象可以包含多个 key/value(键/值)对。
key 必须是字符串,value 可以是合法的 JSON 数据类型(字符串, 数字, 对象, 数组, 布尔值或 null)。

key 和 value 中使用冒号(:)分割。
每个 key/value 对使用逗号(,)分割。
JSON 对象在大括号 {} 中书写:
{key1 : value1, key2 : value2, … keyN : valueN }

对象可以包含多个名称/值对:
{ “name”:“danxia” , “url”:“www.Google.com” }

JSON 可以设置 null 值:
{ “runoob”:null }

三、数据封装

核心结构体

typedef struct cJSON {
struct cJSONnext,prev; / 遍历数组或对象链的前向或后向链表指针/
struct cJSON child; /数组或对象的孩子节点/
int type; /
key的类型*/
char valuestring; /字符串值/
int valueint; /
整数值*/
double valuedouble; /* 浮点数值*/
char string; / key的名字*/
} cJSON;

关于该结构体的几点说明:
cJOSN 结构体是一个双向链表,并且可通过child 指针访问下一层。
结构体成员 type 变量用于描述数据元素的类型(如果是键值对表示 value 值的类型),数据元素可以是字符串、整形、浮点型。
如果是整形值的话可通过 valueint 将值取出
如果是浮点型的话可通过 valuedouble 将值取出
如果是字符串类型的话可通过 valuestring 将值取出
结构体成员 string 表示键值对中键值的名称

核心封装

封装函数

// 空值类型
extern cJSON *cJSON_CreateNull(void);
// 布尔类型
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
// 数值类型
extern cJSON *cJSON_CreateNumber(double num);
// 字符串类型
extern cJSON *cJSON_CreateString(const char *string);
// json数组(创建空数组)
extern cJSON *cJSON_CreateArray(void);
// json对象(创建空对象)
extern cJSON *cJSON_CreateObject(void);

创建数组类型函数

// 创建一个Json数组, 元素为整形
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
// 创建一个Json数组, 元素为浮点
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
// 创建一个Json数组, 元素为字符串类型
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);

释放取消类型函数

//删除JSON结构体
extern cJSON *cJSON_Delete(cJSON *item)
//清空JSON占用的内存空间
static void CJSON_CDECL internal_free(void *pointer)

cJSON_CreateObject 函数可创建一个根对象,返回的是一个 cJSON 指针,在这个指针用完了以后,需要手动调用 cJSON_Delete(root) 进行内存回收。
函数 cJSON_Print() 内部封装了 malloc 函数,所以需要使用 free() 函数释放被 out 占用的内存空间。

Json 数据的封装

Json 对象操作举例

创建一个对象,并向这个对象里添加字符串和整型键值:

int main()
{
    cJSON * root;
    cJSON *arry;

    root=cJSON_CreateObject();                     // 创建根数据对象
    cJSON_AddStringToObject(root,"name","danxia");  // 添加键值对
    cJSON_AddStringToObject(root,"sex","woman");     // 添加键值对
    cJSON_AddNumberToObject(root,"age",18);        // 添加键值对

    char *out = cJSON_Print(root);   // 将json形式转换成字符串
    printf("%s\n",out);

    // 释放内存  
    cJSON_Delete(root);  
    free(out);        
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

运行结果:

{
 "name": "danxia",
 "sex": "woman",
 "age": 18
}
  • 1
  • 2
  • 3
  • 4
  • 5

Json 数组操作举例

创建一个数组,并向数组添加一个字符串和一个数字

int main(int argc, char **argv)
{
    cJSON *root;
    root = cJSON_CreateArray();
    cJSON_AddItemToArray(root, cJSON_CreateString("Hello world"));
    cJSON_AddItemToArray(root, cJSON_CreateNumber(18)); 
    // char *s = cJSON_Print(root);
    char *s = cJSON_PrintUnformatted(root);
    if(s)
    {
        printf(" %s \n",s);
        free(s);
    }
    cJSON_Delete(root);
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

运行结果:

["Hello world",18]
  • 1

Json 对象、数组嵌套使用

对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字

int main(int argc, char **argv)
{
    cJSON *root, *body, *list;
    // josn 对象 root
    root = cJSON_CreateObject();
    // root 添加键值对 person:json数组A
    cJSON_AddItemToObject(root,"person", body = cJSON_CreateArray());
    // json数组A 添加Json对象B
    cJSON_AddItemToArray(body, list = cJSON_CreateObject());
    // 在json对象B中添加键值对: "name":"danxia"
    cJSON_AddStringToObject(list,"name","danxia");
    // 在json对象B中添加键值对: "age":18
    cJSON_AddNumberToObject(list,"age",18);
 
    // char *s = cJSON_Print(root);
    char *s = cJSON_PrintUnformatted(root);
    if(s)
    {
        printf(" %s \n",s);
        free(s);
    }
    if(root)
    {
        cJSON_Delete(root); 
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
{
    "person":[{
        "name":"danxia",
        "age":18
    }]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

解析 Json 字符串

解析 Json 对象
C语言写的格式

{\"name\":\"danxia\",\"sex\":\"woman\",\"age\":18}
  • 1

代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
 
int main()
{
    cJSON *json, *name, *sex, *age;  
    char* out="{\"name\":\"luffy\",\"sex\":\"man\",\"age\":19}";
 
    json = cJSON_Parse(out); //解析成json形式
    name = cJSON_GetObjectItem(json, "name");  //获取键值内容
    sex = cJSON_GetObjectItem(json, "sex");
    age = cJSON_GetObjectItem(json, "age");
 
    printf("name:%s,sex:%s,age:%d\n", name->valuestring, sex->valuestring, age->valueint);
 
    cJSON_Delete(json);  //释放内存 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

输出结果(串口实际显示):

name:danxia,sex:woman,age:18
  • 1

解析嵌套的 Json 对象

解析一个嵌套的 Json 对象,数据如下:
{“list”:{“name”:“danxia”,“age”:18},“other”:{“name”:“ace”}}

int main()
{
    char *s = "{\"list\":{\"name\":\"danxia\",\"age\":18},\"other\":{\"name\":\"ace\"}}";
    cJSON *root = cJSON_Parse(s);
    if(!root) 
    {
        printf("get root faild !\n");
        return -1;
    }

    cJSON *js_list = cJSON_GetObjectItem(root, "list");
    if(!js_list) 
    {
        printf("no list!\n");
        return -1;
    }
    printf("list type is %d\n",js_list->type);

    cJSON *name = cJSON_GetObjectItem(js_list, "name");
    if(!name) 
    {
        printf("No name !\n");
        return -1;
    }
    printf("name type is %d\n",name->type);
    printf("name is %s\n",name->valuestring);

    cJSON *age = cJSON_GetObjectItem(js_list, "age");
    if(!age) 
    {
        printf("no age!\n");
        return -1;
    }
    printf("age type is %d\n", age->type);
    printf("age is %d\n",age->valueint);

    cJSON *js_other = cJSON_GetObjectItem(root, "other");
    if(!js_other) 
    {
        printf("no list!\n");
        return -1;
    }
    printf("list type is %d\n",js_other->type);

    cJSON *js_name = cJSON_GetObjectItem(js_other, "name");
    if(!js_name) 
    {
        printf("No name !\n");
        return -1;
    }
    printf("name type is %d\n",js_name->type);
    printf("name is %s\n",js_name->valuestring);

    if(root)
    {
        cJSON_Delete(root);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

结果为:

list type is 6
name type is 4
name is danxia
age type is 3
age is 18
list type is 6
name type is 4
name is ace
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

标题解析 Json 数组

Json 字符串是一个 Json 数组格式,处理方式和 Json 对象差不多,比如我们要解析如下字符串:
{“names”:[“danxia”,“lucky”]}

int main(int argc, char **argv)
{
    char *s = "{\"names\":[\"danxia\",\"lucky\"]}";
    cJSON *root = cJSON_Parse(s);
    if(!root) 
    {
        printf("get root faild !\n");
        return -1;
    }
    cJSON *js_list = cJSON_GetObjectItem(root, "names");
    if(!js_list)
    {
        printf("no list!\n");
        return -1;
    }
    int array_size = cJSON_GetArraySize(js_list);
    printf("array size is %d\n",array_size);
    for(int i=0; i< array_size; i++) 
    {
        cJSON *item = cJSON_GetArrayItem(js_list, i);
        printf("item type is %d\n",item->type);
        printf("%s\n",item->valuestring);
    }

    if(root)
    {
        cJSON_Delete(root);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

标题解析嵌套的 Json 对象和数组

Json 字符串最复杂:莫过于 Json 对象和 Json 数组嵌套的形式.
下面通过一个例子演示一下应该如何解析,字符串格式如下:
{“list”:[{“name”:“danxia”,“age”:18},{“name”:“guizhong”,“age”:19}]}

在解析的时候,我们只需要按照从属关系,一层层解析即可:

根节点是一个 Json 对象,基于根节点中的 key 值取出对应的 value 值,得到一个 Json 数组
读出 Json 数组的大小,遍历里边的各个元素,每个元素都是一个 Json 对象
将 Json 对象中的键值对根据 key 值取出对应的 value 值
从取出的 Value 值中读出实际类型对应的数值 示例代码如下:

#include "cJSON.h"
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    char *s = "{\"list\":[{\"name\":\"danxia\",\"age\":18},{\"name\":\"guizhong\",\"age\":19}]}";
    cJSON *root = cJSON_Parse(s);
    if(!root) 
    {
        printf("get root faild !\n");
        return -1;
    }
    cJSON *list = cJSON_GetObjectItem(root, "list");
    if(!list)
    {
        printf("no list!\n");
        return -1;
    }
    int array_size = cJSON_GetArraySize(list);
    printf("array size is %d\n",array_size);
    
    for(int i=0; i< array_size; i++) 
    {
        cJSON* item = cJSON_GetArrayItem(list, i);
        cJSON* name = cJSON_GetObjectItem(item, "name");
        printf("name is %s\n",name->valuestring);
        cJSON* age = cJSON_GetObjectItem(item, "age");
        printf("age is %d\n",age->valueint);
    }

    if(root)
    {
        cJSON_Delete(root);
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

结果为

在这里插入代码片
  • 1

其他例子:

{
    "code":"a2024",
    "cmd":1,
    "data":[   
        {
            "name":"danxia",
            "port":88
        },
        {
            "name":"meixa",
            "port":89
        }
    ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

解析上面的json串

char data[256] = "{\"code\":\"a2024\",\"cmd\":1,\"data\":[{\"name\":\"a\",\"port\":88},{\"name\":\"b\",\"port\":89}]}";
    cJSON *json=cJSON_Parse(data);
    cJSON *item = cJSON_GetObjectItem(json,"code");
    printf("scode : %s\n",item->valuestring);
    item = cJSON_GetObjectItem(json,"cmd");
    printf("cmd   : %d\n",item->valueint);
    cJSON *d_list = cJSON_GetObjectItem(json,"data");
    int arr_size = cJSON_GetArraySize(d_list);
    cJSON* arr_item_list = d_list->child;

    int i = 0;
    int j = 0;
    for(i=0;i <=(arr_size-1);++i){
        cJSON *send_list = cJSON_GetObjectItem(arr_item_list,"name");
        printf("ip : %s\n",send_list->valuestring);
        send_list = cJSON_GetObjectItem(arr_item_list,"port");
        printf("port   : %d\n",send_list->valueint);
        arr_item_list = arr_item_list->next;
    }
    cJSON_Delete(json);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

实用的注意要点:

注意:芯片堆栈大小的设置:0xC00
在这里插入图片描述

在线解析JSON格式数据工具
https://www.bejson.com/
https://www.sojson.com/

持续更新中,有什么好的工具或者东西,欢迎评价留言,谢谢

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/460608
推荐阅读
相关标签
  

闽ICP备14008679号