cJSON应用

目的:
    对字符串进行处理一直是c语言的一个弱项,如果要形成某种格式的数据,要一个一个地去规范化格式,是很恼火的,因此需要使用工具去做这种字符串格式的事。当需要的数据格式为json时,我们可以使用现有的cJson来处理,以达到形成json,解析json的目的。

编译时注意事项:
    在linux下编译cJSON文件,需要链接libm库,如 gcc *.c -l m

一.什么是json
    json就是键值对的集合。而键值对,则是一种一对一关系的结构: name: value。

    最简单的集合里面是这种结构:
    {
        "name1": "value1",
        "name2": "value2",
        "name3": "value3",
        ......
    }

    由于数据间有层级结构,如学科里面有语文、数学、英语等结构,人们希望通过学科(subject)就能快速索引到关注的内容(语文、英语、数学),所以格式变成了这样。
    {
        "name1": "value1",
        "name2": "value2",
        "name3": "value3",
        "subject": {
            "Math":"98",
            "Chinese","99",
            "English","60"
        }
    }
    在此我们看到了即使复杂一点的json结构,也是键值结构: name: value ,不同的只是这个value变成了一个集合。

    有些数据是高度相似的,如你有很多银行卡,建行的,农行的,交行的,这些银行卡本身也是一个集合(总要有帐号、密码之类的吧),我们习惯用数组去描述它。
    {
        "name1": "value1",
        "name2": "value2",
        "subject": {
            "Math":"98",
            "Chinese","99",
            "English","60"
        }
        "bankcard":    [
            {
                "bankname":    "CCB",
                "bankcard":    "123456",
                "bankpwd":    "543254"
            }, {
                "bankname":    "ABC",
                "bankcard":    "23456",
                "bankpwd":    "543254"
            }
        ]
    }
    这时候我们能通过bandcard去索引到银行卡们。在此:bandcard的value变成了一个数组。而数组由数个结构相似的集合组成。

    这之后的json结构,千变不离其宗,都是这种类似的格式,无非就是多了些层次。

二.创建json数据:

2.1 创建目标:形成以下json格式
{
    "name":    "darren",
    "age":    "25",
    "subject":    {
        "math":    "100",
        "Chinese":    "98"
    },
    "bankcard":    [
        {
            "bankname":    "CCB",
            "bankcard":    "123456",
            "bankpwd":    "543254"
        }, {
            "bankname":    "ABC",
            "bankcard":    "23456",
            "bankpwd":    "543254"
        }
    ]
}


2.2 以下为创建的代码:

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

#include "cJSON.h"

int create_json(char* ret)
{
	//创建根对象
	cJSON *pJsonRoot = cJSON_CreateObject();
	if( NULL == pJsonRoot )
	{
		printf("make pJsonRoot fail\n");
		return -1;
	}

	//创建学科对象
	cJSON *pJsonSubject = cJSON_CreateObject();
	if( NULL == pJsonSubject )
	{
		printf("make pJsonSubject fail\n");
		cJSON_Delete(pJsonRoot);
		return -2;
	}
  	
  	//创建银行卡数组对象
	cJSON *pJsonBankcard = cJSON_CreateArray();
	if( NULL == pJsonBankcard )
	{
		printf("make pJsonBankcard fail\n");
		cJSON_Delete(pJsonRoot);
		cJSON_Delete(pJsonSubject);
		return -3;
	}
    
	//创建建行卡对象
	cJSON *pJsonCcb = cJSON_CreateObject();
	if( NULL == pJsonCcb )
	{
		printf("make pJsonSubject fail\n");
		cJSON_Delete(pJsonRoot);
		cJSON_Delete(pJsonSubject);
		cJSON_Delete(pJsonBankcard);
		return -4;
	}
    
	//创建农行卡对象
	cJSON *pJsonAbc = cJSON_CreateObject();
	if( NULL == pJsonAbc )
	{
		printf("make pJsonSubject fail\n");
		cJSON_Delete(pJsonRoot);
		cJSON_Delete(pJsonSubject);
		cJSON_Delete(pJsonBankcard);
		cJSON_Delete(pJsonCcb);
	} 

	/*
		添加元素到建行卡对象中,组成:
   		{
			"bandname":	"CCB",
			"bandcard":	"123456",
			"bandpwd":	"543254"
		}
	*/
	cJSON_AddStringToObject(pJsonCcb,"bankname","CCB");
	cJSON_AddStringToObject(pJsonCcb,"bankcard","123456");
	cJSON_AddStringToObject(pJsonCcb,"bankpwd","543254");

	/*
 		添加元素到农行卡对象中,组成:
		{
			"bandname":	"ABC",
			"bandcard":	"23456",
			"bandpwd":	"543254"
		}
	*/
	cJSON_AddStringToObject(pJsonAbc,"bankname","ABC");
 	cJSON_AddStringToObject(pJsonAbc,"bankcard","23456");
	cJSON_AddStringToObject(pJsonAbc,"bankpwd","543254");

	/*
    		两个银行卡添加到数组中,组成:
    		[
			{
				"bandname":	"CCB",
				"bandcard":	"123456",
				"bandpwd":	"543254"
			}, {
				"bandname":	"ABC",
				"bandcard":	"23456",
				"bandpwd":	"543254"
			}
		]
	*/
	cJSON_AddItemToArray(pJsonBankcard,pJsonCcb);
	cJSON_AddItemToArray(pJsonBankcard,pJsonAbc);

	/*
    		添加数学、语文到学科对象,组成:
    		{
			"math":	"100",
			"Chinese":	"98"
		}
	*/
	cJSON_AddStringToObject(pJsonSubject,"math","100");
	cJSON_AddStringToObject(pJsonSubject,"Chinese","98");

	/*
    		添加名字、岁数等String类型的元素到根对象
    		添加学科对象到根对象
    		添加银行卡数组对象到根对象
    		最终形成我们的目标json格式。
	*/
	cJSON_AddStringToObject(pJsonRoot,"name","darren");
	cJSON_AddStringToObject(pJsonRoot,"age","25");
	cJSON_AddItemToObject(pJsonRoot,"subject",pJsonSubject);
	cJSON_AddItemToObject(pJsonRoot,"bankcard",pJsonBankcard);
    

	char* out = cJSON_Print(pJsonRoot);
	//printf("Json = %s\n",out);
	memcpy(ret,out,strlen(out));
	cJSON_Delete(pJsonRoot);
	free(out);
	return 0;
}

int main()
{
	char buffer[2048] = "";
	create_json(buffer);
	printf("buffer = %s\n",buffer);
	return 0;
}

2.3 代码注意事项
    1.
        cJSON_CreateObject(),cJSON_CreateArray() 函数申请了内存空间,需调用 cJSON_Delete()函数去释放内存。

    2.如:
        cJSON *pJsonRoot = cJSON_CreateObject();
        cJSON *pJsonSubject = cJSON_CreateObject();
        cJSON_AddItemToObject(pJsonRoot,"subject",pJsonSubject);
        即pJsonRoot包含了pJsonSubject,此时只需要 cJSON_Delete(pJsonRoot);pJsonSubject对象会被随之释放掉。

    3.
        char* out = cJSON_Print(pJsonRoot);
        必须调用free(out)去释放内存。

三.解析json

3.1目标:
    1.在事先知道json格式的情况下(一般是约定好的格式),通过name去获取其value
    2.解析未知的json,取出所有的name 和value
    代码以上述组成的json来去解析。

3.2 代码:

//sign表层级
void print_json(cJSON* data, int sign)
{
	if(!data)
		return;
	int count = sign;
	while(count--)
	{
		printf("\t");
	}

	//对象类型为cJSON_String,打印name,value
	if(data->type == cJSON_String)
	{
		printf("sign = %d: name = %s, value = %s\n",sign,data->string,data->valuestring);
	}
	//对象为 cJSON_Array 或 cJSON_Object
	else if(data->type == cJSON_Array || data->type == cJSON_Object)
	{
		//打印name(数组里的元素是无name的)
		printf("sign = %d: name = %s\n",sign,data->string);
		int i = 0;
		//获取对象里元素个数
		for(; i < cJSON_GetArraySize(data); i++)
		{
			cJSON* item = cJSON_GetArrayItem(data,i);
			//迭代,并增加层级
			print_json(item,sign+1);
		}
	}
}

void process_json(char* data)
{
	//字符串转json对象,使用结束后要delete掉,否则内存泄漏
	cJSON* pRoot = cJSON_Parse(data);
	if( pRoot == NULL )
	{
		printf("data is wrong\n");
		return;
	}
	
	//假定知道json对象格式内容
	/*
		从pRoot集合,获取名称为"name"的对象,其类型为:cJSON_String
	*/
	cJSON* pName = cJSON_GetObjectItem(pRoot,"name");
	printf("name=%s, value=%s\n",pName->string,pName->valuestring);
    
	/*
		从pRoot集合,获取名称为"subject"的对象,其类型为:cJSON_Object
	*/ 
	cJSON* pSubject = cJSON_GetObjectItem(pRoot,"subject");
	if( pSubject->type == cJSON_Object )
	{
		/*
			从pSubject集合,获取名称为"math"的对象,其类型为:cJSON_String
		*/
		cJSON* pMath = cJSON_GetObjectItem(pSubject,"math");
		printf("name=%s, value=%s\n",pMath->string,pMath->valuestring);
	}
    
	/*
		从pRoot集合,获取名称为"subject"的对象,其类型为:cJSON_Array
	*/
	cJSON* pBankcard = cJSON_GetObjectItem(pRoot,"bankcard");
        if( pBankcard->type == cJSON_Array )
	{
		/*
			从pBankcard数组,获取它第0个元素,其类型为:cJSON_Object
		*/
		cJSON* pArray0 = cJSON_GetArrayItem(pBankcard,0);
		if( pArray0->type == cJSON_Object )
		{
		    /*
				从pBankcard数组第0元素,获取名称为"bankname"的对象,其类型为:cJSON_String
			*/
			cJSON* pBankName = cJSON_GetObjectItem(pArray0,"bankname");
		    printf("name=%s, value=%s\n",pBankName->string,pBankName->valuestring);
		}

	}
    	
	//假定未知json数据格式,逐个去获取并打印
	print_json(pRoot,0);

	//释放内存
	cJSON_Delete(pRoot);
}

int main()
{
	char buffer[2048] = "";
	create_json(buffer);
	printf("buffer = %s\n",buffer);
	process_json(buffer);
	return 0;
}

3.3 代码注意事项
    使用 cJSON* pRoot = cJSON_Parse(data),结束后需要 cJSON_Delete(pRoot),否则会内存泄漏





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
cJSON遍历实例代码如下: ```c #include <stdio.h> #include "cJSON.h" void traverse(cJSON *root) { if (root == NULL) { return; } switch (root->type) { case cJSON_False: printf("False\n"); break; case cJSON_True: printf("True\n"); break; case cJSON_NULL: printf("NULL\n"); break; case cJSON_Number: printf("Number: %lf\n", root->valuedouble); break; case cJSON_String: printf("String: %s\n", root->valuestring); break; case cJSON_Array: printf("Array:\n"); cJSON *child = root->child; while (child != NULL) { traverse(child); child = child->next; } break; case cJSON_Object: printf("Object:\n"); cJSON *item = root->child; while (item != NULL) { printf("Key: %s\n", item->string); traverse(item); item = item->next; } break; default: break; } } int main() { const char *jsonStr = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}"; cJSON *root = cJSON_Parse(jsonStr); traverse(root); cJSON_Delete(root); return 0; } ``` 上述代码通过cJSON库解析了一个JSON字符串,并实现了遍历JSON对象的功能。遍历函数traverse()通过递归地遍历cJSON对象的子节点,根据节点的类型打印出相应的信息。在主函数中,我们首先将JSON字符串解析为cJSON对象,然后调用traverse()函数进行遍历,最后释放资源。 希望以上代码能对您有所帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [ESP32-C3入门教程 系统篇④——cJSON应用实例 | C语言中超轻量级JSON解析器](https://blog.csdn.net/kangweijian/article/details/124579543)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [cJSON方法详解](https://blog.csdn.net/jhyBOSS/article/details/108375390)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值