当前位置:   article > 正文

C语言解析 json文件_c语言json数据解析

c语言json数据解析

C语言解析 json文件

使用C语言解析json文件,使用过几次每次都要查资料,所以写个帖子以后再碰到就不用花太多时间了,有兴趣的同学可以简单借鉴

下载cJSON库

可以访问这位大佬的这篇文章
https://blog.csdn.net/nanfeibuyi/article/details/86605234
直面大佬

我用大佬的方法编译链接库的时候出现过一点问题,这里也记录一下
https://blog.csdn.net/yjk13703623757/article/details/53217377
直面大佬

我用的是文章中的第二个方法将解压文件夹中的文件放到

/usr/loca/lib
  • 1

后面的步骤按链接文章中的操作就行了

不使用.so文件,直接使用.c .h文件

如果不想要链接库的话可以下载这个文件
cJSON库https://sourceforge.net/projects/cjson/
里面有.c和.h文件编译的时候放到一起就行了
里面的函数和cJSON库中的函数是一样的,只是使用起来不需要配置和链接库

这里在贴个大佬的连接,讲的十分详细
https://blog.csdn.net/Mculover666/article/details/103796256
直面大佬

Linux下的一个json工具

这个也是参考大佬的, 可装也可以不用装,效果如下:
在这里插入图片描述
这是大佬的链接:https://linux.cn/article-12915-1.html
添加链接描述

cJson源码中一些需要了解的内容

 1. 将json文件解析成cJSON对象后,cJSON内部使用链表的方式存储键值对,所以使用后需要及时释放内存
 2. typedef struct cJSON {
	struct cJSON *next,*prev;	//	用于链表的构建
	struct cJSON *child;		

	int type;					//	记录当前cJSON结构体存放的类型(cJSON_Object、cJSON_Array、cJSON_String、cJSON_Number、cJSON_NULL、cJSON_True、cJSON_False)

	char *valuestring;			//	存放字符串值
	int valueint;				//	存放整型值
	double valuedouble;			//	存放浮点型值

	char *string;				//	存放键名
} cJSON;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

Linux 和 win都通用的一个代码

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

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <unistd.h>

// #define WRITE_
// #define READ_
// #define CHANG_

int main(void)
{

		//编辑json文件内容

#ifdef  WRITE_
	//打开json文件并创建数据

	//创建一个空的文档对象
	cJSON* json = cJSON_CreateObject();

	//向文档中增加一个键值对{"name":"zww"}
	cJSON_AddItemToObject(json, "name", cJSON_CreateString("calmReed"));
	cJSON_AddItemToObject(json, "age", cJSON_CreateNumber(20));

	//宏的使用    效果和上面的一样,只是看起来更简短
	cJSON_AddNumberToObject(json, "score", 12);
	cJSON_AddStringToObject(json, "address", "jiangxi");

	cJSON* array = NULL; //数组
	cJSON_AddItemToObject(json, "love", array = cJSON_CreateArray()); //创建一个数组到json这个类中

	//创建一个对象
	cJSON *myjson = cJSON_CreateObject();
	//创建键值对到对象中
	cJSON_AddItemToObject(myjson, "who", cJSON_CreateString("me"));
	//在数组中添加一个对象
	cJSON_AddItemToArray(array, myjson);

	//向数组中添加一个数字
	cJSON_AddItemToArray(array, cJSON_CreateNumber(20));

	//将json结构体格式化到缓冲区
	char *buf = cJSON_Print(json);

	//打开文件用以写入json数据
	FILE *fp = fopen("test2.json", "w");
	fwrite(buf, 1, strlen(buf), fp);
    //  使用之后注意释放字符串内存
	free(buf);
	fclose(fp);

	//释放json结构体所占的内存
	cJSON_Delete(json);

#endif

	//读取json文件内容
#ifdef READ_

	//打开文件并读取数据
	//打开保存JSON数据的文件
	int fd = open("test2.json",O_RDWR);
	if(fd < 0)
	{
		perror("open fail\n");
		return -1;
	}

	//读取文件中的数据
	char buf[2048]={0};
	int ret = read(fd, buf, sizeof(buf));
	if(ret == -1)
	{
		perror("read error");
		return -1;
	}

	close(fd);

	//把该字符串数据转换成JSON数据(对象)  开始的对象为最外层的对象
	cJSON *root=cJSON_Parse(buf);
	if(root == NULL)
	{
		printf("parse error\n");
		return -1;
	}

	/*
	 * 取对象中的value值
	 * */
	cJSON *_name = cJSON_GetObjectItem(root,"name");//获取键"name"对应的JSON值
	if(_name == NULL)
	{
		printf("GetObjec error\n");
		return -1;
	}

    //  如果单纯只是为了打印,直接使用_name->valuestring就行
    char *_name_c = (char *)malloc(strlen(_name->valuestring)+1);
    strcpy(_name_c, _name->valuestring);
	printf("name = [%s]\n", _name_c);
    free(_name_c);

	/*
	 * 	获取数组中的内容
	 *
	 * */
	//当前的value1 是一个数组对象
	cJSON * _love = cJSON_GetObjectItem(root,"love");
	if(_love == NULL)
	{
		printf("GetObjectItem error\n");
		return -1;
	}
	//获取该数组对象的大小
	int _len = cJSON_GetArraySize(_love);
	printf("love arry len = %d\n",_len);

	//根据下标获取对象
	int i = 0;
	cJSON * type_value = NULL;
	for(i=0;i<_len;i++)
	{
		//获取数组中的每个内容, 如果对象则进一步解析
		type_value = cJSON_GetArrayItem(_love,i);

		if(type_value == NULL)
		{
			printf("GetObjectItem error\n");
			return -1;
		}
        if(type_value->type == cJSON_Object)
        {
            cJSON *_who = cJSON_GetObjectItem(type_value, "who");
            printf("love[%d]=%s\n",i, _who->valuestring);
        }
        if(type_value->type == cJSON_Number)
        {
            printf("love[%d]=%d\n",i, type_value->valueint);
        }
	}

	cJSON_Delete(root);


#endif

#ifdef CHANG_

	/*
	extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem);	
	extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
	extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
	*/
	//修改数据并保存
	int fd = open("test2.json",O_RDWR);
	if(fd < 0)
	{
		perror("open fail\n");
		return -1;
	}

	//读取文件中的数据
	char buf[2048]={0};
	int ret = read(fd, buf, sizeof(buf));
	if(ret == -1)
	{
		perror("read error");
		return -1;
	}

	lseek(fd, 0, SEEK_SET);//注意将fd放到开头

	//把该字符串数据转换成JSON数据(对象)  开始的对象为最外层的对象
	cJSON *root=cJSON_Parse(buf);
	if(root == NULL)
	{
		printf("parse error\n");
		return -1;
	}

	//修改值
	cJSON_ReplaceItemInObject(root, "name",cJSON_CreateString("calm_reed"));
	cJSON_ReplaceItemInObject(root, "age",cJSON_CreateNumber(11));

	//修改数组中的对象的值
	cJSON *arry_love = cJSON_GetObjectItem(root,"love");
	cJSON *type_who = cJSON_GetArrayItem(arry_love, 0);
	cJSON_ReplaceItemInObject(type_who, "who",cJSON_CreateString("you"));

    //  直接修改cJSON中的值也是可以的, 需要注意的是如果是整型,需要用valuedouble才能修改成功
    // cJSON *value_num = cJSON_GetArrayItem(arry_love, 1);
    // value_num->valuedouble = 111;

	//将json结构体格式化到缓冲区
    char *_out = cJSON_Print(root);
	strcpy(buf, _out);
	//将修改后的数据写入到文件中
	write(fd, buf, strlen(buf));
    free(_out);
	close(fd);
	//释放json结构体所占的内存

	cJSON_Delete(root);

#endif
	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
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219

代码分为三个模块,可以使用define进行切换


//#define WRITE_  //写
//#define READ_   //读
//#define CHANG_  //改
  • 1
  • 2
  • 3
  • 4

1. 写json文件

流程:
1.创建cJSON *对象 ->
2.使用json库中的函数创建信息 ->
3.将对象转换为字符串格式 ->
4.将字符串写入到文件中

上面的代码已经将大部分的种类创建列举出来了,其他的创建也是大同小异
需要注意的是 :
1.数组中似乎只能创建key没有value, 如果要键值对的话,需要在数组中创建对象
2.需要及时释放内存cJSON_Delete

2. 读json文件内容

流程:
1.打开文件 ->
2.将文件内容放到字符串中 ->
3.将字符串转换为cJSON *对象 ->
4.使用json库中的函数获取需要的信息

运行结果

name = [calmReed]
love arry len = 2
love[0]=me
love[1]=20
  • 1
  • 2
  • 3
  • 4

读取和添加也差不多只不过是函数从Add变成了Get
如果有多层嵌套的解析也是如此,一层一层的获取

3. 修改json文件

流程:
1.打开文件 ->
2.将文件内容放到字符串中 ->
3.将字符串转换为cJSON *对象 ->
4.使用json库中的函数修改信息


运行结果
原来的内容
```php
{
	"name":	"calmReed",
	"age":	20,
	"score":	12,
	"address":	"jiangxi",
	"love":	[{
			"who":	"me"
		}, 20]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

修改后的内容

{
	"name":	"calm_reed",
	"age":	11,
	"score":	12,
	"address":	"jiangxi",
	"love":	[{
			"who":	"you"
		}, 20]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

总结几个需要注意的点:

1.修改json文件内容简单来说就是覆盖原有文件中的内容,但我们已经将所有文件内容复制到了字符串中,需要将文件描述符放到文件的开头,否则就不是修改而是追加了
 
2.cJSON_Print()所返回的指针源码中是使用malloc申请过内存的,所以使用之后需要free()释放

3.关于修改的函数问题:
https://blog.csdn.net/Mculover666/article/details/103796256
这篇文章中的第二点
	/*
	 *   String:用于表示该键值对的名称;
		   type:用于表示该键值对中值的类型;
		   valuestring:如果键值类型(type)是字符串,则将该指针指向键值;
		   valueint:如果键值类型(type)是整数,则将该指针指向键值;
		   valuedouble:如果键值类型(type)是浮点数,则将该指针指向键值;
	 * */
可以通过修改结构体中的内容来修改键值,使用源码提供的函数其内部是将原来链表中的节点(需要修改的节点)进行了删除,然后重新创建了一个节点替换上去


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

本文章主要面向于如何使用 cJSON库中的内容,并不深入,如果需要深入的了解可以查看文首的大佬链接,这是本人的第一篇文章,如果有什么错误希望大家能及时回复,希望对大家有帮助

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