用代码详解使用从JSON库实现json文件的序列化和反序列化

用代码详解使用从JSON库实现json文件的序列化和反序列化

了解json

Json入门教程:了解Json基本的概念

json数据类型

  • number:和JavaScript的number完全一致;相当于C中的int类型
  • boolean:就是JavaScript的true或false;相当于c++中的bool类型
  • string:就是JavaScript的string;相当于c++的string类型
  • null:就是JavaScript的null;相当于C的NULL类型
  • array:就是JavaScript的Array表示方式——[];相当于C的数组
  • object:就是JavaScript的{ … }表示方式。相当于C++的类或者C的结构体
    注意:json的数据类型在源码实现中和具体的编程语言有关,比如boolean在C中并没有相应的类型,C相关的实现库可能会用0和1表示。也可以添加头文件#include<stdbool.h>(不推荐)。

格式规范

  • json以大括号起始和结尾
  • 内容都是以键值对的形式存在
  • 所有的键都是字符串
  • 值的类型不一定,属于JavaScript 的基本数据类型
  • 每个键值对以,分割
  • 最后一个键值对不加逗号
{
  "name": "小明",
  "age": 14,
  "gender": true,
  "height": 1.65,
  "grade": null,
  "skills": [
    "JavaScript",
    "Java",
    "Python",
    "Lisp"
  ]
}

json格式校验

格式校验

JSON基本操作

Json序列化:可以理解为利用程序生成Json字符串的过程。
Json反序列化:可以理解为利用程序将已有的Json字符串解析出我们需要的值的过程。

cJson

相关资料

cJSON的github地址(这个不用看,相当于官方源码地址)
github

cJSON 使用详解

https://blog.csdn.net/qq_32172673/article/details/88305781

JSON的简单介绍以及C语言的JSON库使用

https://www.cnblogs.com/liunianshiwei/p/6087596.html

关键接口梳理

/* 类型定义 */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6

/* CJSON核心结构体 */
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;					/* 节点的类型,取值是上面的6种 */

	char *valuestring;			/* 如果类型是cJSON_String,那么值会被存到这里 */
	int valueint;				/* 如果类型是cJSON_Number,且是整型,那么值会被存到这里 */
	double valuedouble;			/* 如果类型是cJSON_Number,且是浮点型,那么值会被存到这里 */

	char *string;				/* 键*/
} cJSON;

/****************************通用接口****************************/
//把传入的字符串转成cJSON的结构(反序列化)
cJSON *cJSON_Parse(const char *value);
//把cJSON结构转成字符串(序列化),调用后需要配合free接口释放malloc的内存
char  *cJSON_Print(cJSON *item);
//无格式化序列化,节省内存,调用后需要配合free接口释放malloc的内存
char  *cJSON_PrintUnformatted(cJSON *item);
//释放节点的内存,防止内存泄露
void   cJSON_Delete(cJSON *c);

/****************************反序列化相关接口****************************/
//获取数组的大小
int	  cJSON_GetArraySize(cJSON *array);
//从array数组中获取第item个子节点
cJSON *cJSON_GetArrayItem(cJSON *array,int item);
//获取object大节点名字叫string的子节点
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
//判断object大节点中是否有名字叫string的小节点
int cJSON_HasObjectItem(cJSON *object,const char *string);

/****************************序列化相关接口****************************/
//创建一个普通节点
cJSON *cJSON_CreateObject(void);
//创建一个数组节点
cJSON *cJSON_CreateArray(void);
//把item节点增加到array的数组节点中
void cJSON_AddItemToArray(cJSON *array, cJSON *item);
//把item节点增加到object中作为子节点,item节点的键名为string
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);

//创建各种类型的cJSON节点
cJSON *cJSON_CreateNull(void);
cJSON *cJSON_CreateTrue(void);
cJSON *cJSON_CreateFalse(void);
cJSON *cJSON_CreateBool(int b);
cJSON *cJSON_CreateNumber(double num);
cJSON *cJSON_CreateString(const char *string);
cJSON *cJSON_CreateArray(void);
cJSON *cJSON_CreateObject(void);

例子

反序列化

使用cJSON库对下面的JSON文件进行反序列化操作。ver和login的子节点直接打印即可,data的数据节点解析后形成链表存储(将下面内容存为文件,读取后解析即可)。

{
	"ver": "1.0",
	"login": {
		"user": "zhangsan",
		"pwd": 1234
	},
	"data": [{
      "key": 1,
      "type": 2,
      "val": "10"
    },
    {
      "key": 2,
      "type": 1,
      "val": "0"
    },
    {
      "key": 3,
      "type": 3,
      "val": "22.5"
    }
	]
}

注意:上面的所有val值都是string类型,解析出来存到节点前,需要根据type的类型来进行转换,按照相应的类型存储到共用体中。
提示:对于数据解析后,形成新的节点存放链表,最好的方式是为每个节点分配单独的内存。例:

struct data {
    int key;
    int type;
    union val_t val;
    struct list_head list;
};

struct data *node = (struct data *)malloc(sizeof(struct data));
node->xxx = xxx;
插入链表即可
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "cJSON.h"

typedef union
{
    bool bool_val;
    int int_val;
    float float_val;
} val_t;

typedef struct data
{
    int key;
    int type;
    val_t val;
} data_t;

typedef struct node
{
    data_t data;
    struct node *next;
} node_t;

int main()
{
    FILE *fp = fopen("item.json", "r");
    if (!fp)
    {
        printf("Failed to open file\n");
        return 1;
    }

    char buffer[1024];
    fread(buffer, 1, sizeof(buffer), fp);
    fclose(fp);

    cJSON *root = cJSON_Parse(buffer);
    if (!root)
    {
        printf("Failed to parse JSON: %s\n", cJSON_GetErrorPtr());
        return 1;
    }

    cJSON *ver = cJSON_GetObjectItem(root, "ver");
    if (ver && ver->type == cJSON_String)
    {
        printf("ver: %s\n", ver->valuestring);
    }

    cJSON *login = cJSON_GetObjectItem(root, "login");
    if (login && login->type == cJSON_Object)
    {
        cJSON *user = cJSON_GetObjectItem(login, "user");
        if (user && user->type == cJSON_String)
        {
            printf("login.user: %s\n", user->valuestring);
        }

        cJSON *pwd = cJSON_GetObjectItem(login, "pwd");
        if (pwd && pwd->type == cJSON_Number)
        {
            printf("login.pwd: %d\n", pwd->valueint);
        }
    }

    cJSON *data = cJSON_GetObjectItem(root, "data");
    if (data && data->type == cJSON_Array)
    {
        int size = cJSON_GetArraySize(data);
        node_t *head = NULL, *tail = NULL;
        for (int i = 0; i < size; i++)
        {
            cJSON *item = cJSON_GetArrayItem(data, i);
            if (item && item->type == cJSON_Object)
            {
                data_t *node_data = malloc(sizeof(data_t));
                memset(node_data, 0, sizeof(data_t));

                cJSON *key = cJSON_GetObjectItem(item, "key");
                if (key && key->type == cJSON_Number)
                {
                    node_data->key = key->valueint;
                }

                cJSON *type = cJSON_GetObjectItem(item, "type");
                if (type && type->type == cJSON_Number)
                {
                    node_data->type = type->valueint;
                }

                cJSON *val = cJSON_GetObjectItem(item, "val");
                if (val)
                {
                    switch (node_data->type)
                    {
                    case 1:
                        if (val->type == cJSON_String)
                        {
                            const char *val_str = val->valuestring;
                            node_data->val.bool_val = atoi(val_str);
                        }
                        break;
                    case 2:
                        if (val->type == cJSON_String)
                        {
                            const char *val_str = val->valuestring;
                            node_data->val.int_val = atoi(val_str);
                        }
                        break;
                    case 3:
                        if (val->type == cJSON_String)
                        {
                            const char *val_str = val->valuestring;
                            node_data->val.float_val = atof(val_str);
                        }
                        break;
                    }
                }

                node_t *node = malloc(sizeof(node_t));
                node->data = *node_data;
                node->next = NULL;

                if (head == NULL)
                {
                    head = node;
                    tail = node;
                }
                else
                {
                    tail->next = node;
                    tail = node;
                }

                free(node_data);
            }
        }

        cJSON_Delete(root);

        node_t *node = head;
        while (node)
        {
            printf("key: %d, type: %d, val: ", node->data.key, node->data.type);
            switch (node->data.type)
            {
            case 1:
                printf("%d\n", node->data.val.bool_val);
                break;
            case 2:
                printf("%d\n", node->data.val.int_val);
                break;
            case 3:
                printf("%.1f\n", node->data.val.float_val);
                break;
            }

            node = node->next;
        }


        node = head;
        while (node)
        {
            node_t *temp = node;
            node = node->next;
            free(temp);
        }

        return 0;
    }

    return 0;
}

序列化

使用cJSON库序列化出下面的JSON内容。

{
  "name": "小明",
  "age": 14,
  "gender": true,
  "height": 1.65,
  "grade": null,
  "skills": [
    "JavaScript",
    "Java",
    "Python",
    "Lisp"
  ]
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "cJSON.h"
#include <windows.h>

// {
//   "name": "小明",
//   "age": 14,
//   "gender": true,
//   "height": 1.65,
//   "grade": null,
//   "skills": [
//     "JavaScript",
//     "Java",
//     "Python",
//     "Lisp"
//   ]
// }
int main()
{
    SetConsoleOutputCP(CP_UTF8);
    cJSON *root = cJSON_CreateObject();

    cJSON_AddStringToObject(root, "name", "小明");
    cJSON_AddNumberToObject(root, "age", 14);
    cJSON_AddBoolToObject(root, "gender", true);
    cJSON_AddNumberToObject(root, "height", 1.65);
    cJSON_AddNullToObject(root, "grade");
    cJSON *skills = cJSON_CreateArray();
    cJSON_AddItemToObject(root, "skills", skills);
    cJSON_AddItemToArray(skills, cJSON_CreateString("JavaScript"));
    cJSON_AddItemToArray(skills, cJSON_CreateString("Java"));
    cJSON_AddItemToArray(skills, cJSON_CreateString("Python"));
    cJSON_AddItemToArray(skills, cJSON_CreateString("Lisp"));
    printf("%s\n", cJSON_Print(root));
    cJSON_Delete(root);
    return 0;
}

序列化和反序列化

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "cJSON.h"
#include <windows.h>

typedef union val_t
{
    bool bool_val;
    int int_val;
    float float_val;
} val_t;

typedef struct data_t
{
    int key;
    int type;
    val_t val;
} data_t;

int main(int argc, char const *argv[])
{
    SetConsoleOutputCP(CP_UTF8);
    // 反序列化
    FILE *fp = fopen("item.json", "r");
    char buffer[1024];
    fread(buffer, 1, sizeof(buffer), fp);
    fclose(fp);

    cJSON *root = cJSON_Parse(buffer);
    if (!root)
    {
        printf("Failed to parse JSON: %s\n", cJSON_GetErrorPtr());
        return -1;
    }

    // 获取ver
    cJSON *ver = cJSON_GetObjectItem(root, "ver");
    if (ver && ver->type == cJSON_String)
    {
        printf("%s: %s\n", ver->string, ver->valuestring);
    }

    // 获取login
    cJSON *login = cJSON_GetObjectItem(root, "login");
    cJSON *user = cJSON_GetObjectItem(login, "user");
    if (user && user->type == cJSON_String)
    {
        printf("%s: %s\n", user->string, user->valuestring);
    }
    cJSON *pwd = cJSON_GetObjectItem(login, "pwd");
    if (pwd && pwd->type == cJSON_Number)
    {
        printf("%s: %d\n", pwd->string, pwd->valueint);
    }

    // 获取data
    cJSON *data = cJSON_GetObjectItem(root, "data");
    if (data && data->type == cJSON_Array)
    {
        int size = cJSON_GetArraySize(data);
        data_t *items = malloc(size * sizeof(data_t));
        memset(items, 0, size * sizeof(data_t));

        for (int i = 0; i < size; i++)
        {
            cJSON *item = cJSON_GetArrayItem(data, i);
            if (item && item->type == cJSON_Object)
            {
                cJSON *key = cJSON_GetObjectItem(item, "key");
                if (key && key->type == cJSON_Number)
                {
                    items[i].key = key->valueint;
                }

                cJSON *type = cJSON_GetObjectItem(item, "type");
                if (type && type->type == cJSON_Number)
                {
                    items[i].type = type->valueint;
                }

                cJSON *val = cJSON_GetObjectItem(item, "val");
                if (val)
                {
                    switch (items[i].type)
                    {
                    case 1:
                    case 2:
                        if (val->type == cJSON_String)
                        {
                            items[i].val.int_val = atoi(val->valuestring);
                        }
                        break;
                    case 3:
                        if (val->type == cJSON_String)
                        {
                            items[i].val.float_val = atof(val->valuestring);
                        }
                        break;
                    }
                }
            }
        }

        // Print the data items
        for (int i = 0; i < size; i++)
        {
            printf("key: %d, type: %d, val: ", items[i].key, items[i].type);
            switch (items[i].type)
            {
            case 1:
            case 2:
                printf("%d\n", items[i].val.int_val);
                break;
            case 3:
                printf("%f\n", items[i].val.float_val);
                break;
            }
        }

        free(items);
    }

    cJSON_Delete(root);

    // 序列化
    cJSON *root1 = cJSON_CreateObject();
    cJSON_AddStringToObject(root1, "name", "小明");
    cJSON_AddNumberToObject(root1, "age", 14);
    cJSON_AddBoolToObject(root1, "gender", true);
    cJSON_AddNumberToObject(root1, "height", 1.65);
    cJSON_AddNullToObject(root1, "grade");

    cJSON *skills = cJSON_CreateArray();
    cJSON_AddItemToObject(root1, "skills", skills);
    cJSON_AddItemToArray(skills, cJSON_CreateString("JavaScript"));
    cJSON_AddItemToArray(skills, cJSON_CreateString("Java"));
    cJSON_AddItemToArray(skills, cJSON_CreateString("Python"));
    cJSON_AddItemToArray(skills, cJSON_CreateString("Lisp"));

    char *out = cJSON_Print(root1);
    printf("%s\n", out);
    free(out);

    cJSON_Delete(root1);

    return 0;
}

注意

编译cJSON库时候,gcc需要增加 -l m选项,动态链接math库。
gcc xxx.c -o xxx cJSON.c -lm

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值