使用cJSON

JSON数据交互与cJSON解析技术详解

JSON是一种比XML更轻量级的数据交换格式,关于JSON的基础知识,参考 http://json.org/

JSON(JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming LanguageStandard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.

 

 

cJSON也存在几个弱点:

1,不支持[1,2,3,]和{"one":1,}最后多余的那个逗号。这是C语言就开始支持的,JSON RFC文档中没有对此说明,只能说这是扩展功能吧。

2 ,不支持/*注释*/,和//单行注释。这也是扩展功能。C/C++/JAVA/JavaScript都支持注释,所以我也希望在json文件中写点注释。

3 ,使用了个全局变量指示出错位置。这个在多线程时就有问题啦。

4, 没有封装文件操作,用户需要自己读写文件。

虽然功能不是非常强大(上面124都是非常容易添加少数几行代码都可以支持的),但cJSON的小身板和速度是最值得赞赏的。其代码被非常好地维护着,结构也简单易懂,可以作为一个非常好的C语言项目进行学习(支持上面12两个功能可以作为学习后的作业)。其解析核心是通过递归函数完成的,不过放心它的每个函数都非常非常节省资源。

 

使用如下

void main()
{
 char  *jsonStr="{\"weatherinfo\":{\"city\":\"宝鸡\",\"cityid\":\"101110901\",\"temp\":\"23\",\"WD\":\"东风\",\"WS\":\"2级\",\"SD\":\"83%\",\"WSE\":\"2\",\"time\":\"18:00\",\"isRadar\":\"0\",\"Radar\":\"\"}}";
 cJSON *root;
 cJSON *item;
 char  *str;

 root=cJSON_Parse(jsonStr);
 if (!root) 
 {
  printf("Error before: [%s]\n",cJSON_GetErrorPtr());
 }
 else
 {
  item=cJSON_GetObjectItem(root,"weatherinfo");
  if(item)
  {
   str=cJSON_GetObjectItem(item,"city")->valuestring;
   printf("city: [%s]\n",str);
   str=cJSON_GetObjectItem(item,"cityid")->valuestring;
   printf("cityid: [%s]\n",str);
   str=cJSON_GetObjectItem(item,"temp")->valuestring;
   printf("temp: [%s]\n",str);

   free(item);
  }
  free(root);
 }

 

在cJSON.h中有如下定义

/* cJSON Types: */
#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

 

下面这很详细 copy过来看看:

原文:http://www.gejo.in/archives/690

cJSON* pRoot = cJSON_Parse ( jsonString );
    while ( pRoot )
    {
        do
        {
            pItem = cJSON_GetObjectItem ( pRoot, "Code");
            if(pItem){
                switch(pItem->type)
                {
                    case 0:
                        strcpy(out,pItem->valuestring);
                        break;
                     case 1:
                        sprintf(out,"%d",pItem->valueint);
                        break;
                     case 2://long long
                        sprintf(out,"%lld",pItem->valuellong);
                        break;
                     case 3://double
                        sprintf(out,"%lf",pItem->valuedouble);
                        break;
                     case 4: //array
                        nCount = cJSON_GetArraySize( pItem); //获取pArray数组的大小,仅对字符串元素?
                        for( i= 0; i < nCount; i++)
                        {
                            pArrayItem = cJSON_GetArrayItem(pItem, i);
                            strcat(out,cJSON_Print( pArrayItem));
                           // sprintf(out,"%s",out,pArrayItem);
                        }
                        break;
                }
            }
            else if(pRoot->next)
               pRoot=pRoot->next;
            else break;

        }while(!pItem&&pRoot);
        pRoot=pRoot->child;
    }

 

<think>好的,我现在需要帮用户介绍如何使用cJSON库。用户之前已经问过关于NATS接收方的C++实现,现在转而询问cJSON,这可能意味着他们正在处理JSON数据解析,特别是在C语言环境中。用户可能是在嵌入式系统或资源有限的环境下工作,因为cJSON是一个轻量级的C库,适合这样的场景。 首先,我需要确定用户的需求。他们可能想知道如何在C语言中解析和生成JSON数据,或者他们可能遇到了具体的问题,比如内存管理、数据结构处理等。用户可能已经尝试过其他库,但选择了cJSON因为它的轻量和简单。另外,用户可能对如何集成cJSON到现有项目中有疑问,或者需要示例代码来理解基本用法。 接下来,我需要回顾cJSON的主要功能和特点。cJSON以单文件、MIT许可证、跨平台著称,适合嵌入式系统。它使用链表结构存储数据,支持各种JSON类型,如对象、数组、字符串、数字等。但用户需要注意它的API使用方式,比如手动内存管理和错误处理。 然后,我应该组织回答的结构,确保覆盖安装、基本用法、创建和解析JSON的示例、内存管理、错误处理以及高级功能。用户可能需要具体的代码示例来快速上手,所以需要提供创建对象、数组,解析JSON字符串,以及处理嵌套结构的例子。同时,要强调内存管理的重要性,因为cJSON需要手动释放内存,避免内存泄漏。 还要考虑用户可能的进阶需求,比如文件操作、Unicode支持,以及性能优化建议。例如,解析大文件时使用流式解析,或者处理特殊字符的情况。此外,指出cJSON的不足,比如性能问题,帮助用户评估是否适合他们的项目。 需要确保回答清晰,步骤分明,代码示例正确,并符合用户之前的格式要求,比如使用中文,正确使用LaTeX排版行内公式,如变量名用$...$包裹。同时,避免使用Markdown,保持文本简洁。 最后,检查是否有遗漏的重要点,比如常见错误或调试技巧,比如使用cJSON_PrintUnformatted来生成紧凑的JSON字符串,或者如何遍历嵌套结构。确保用户能够通过回答解决实际问题,并顺利集成cJSON到他们的项目中。</think>以下是如何在C语言中使用cJSON库处理JSON数据的详细说明,包含基础用法、内存管理、错误处理等核心内容: --- ### 一、cJSON基础介绍 cJSON是一个轻量级(单文件)、MIT许可证的C语言JSON解析库,特点: - 支持JSON标准(RFC 8259) - 仅需`cJSON.c`和`cJSON.h`两个文件 - 内存占用低(适合嵌入式系统) - 使用链表结构存储数据 --- ### 二、安装与集成 1. **获取源码**: ```bash git clone https://github.com/DaveGamble/cJSON.git ``` 2. **添加到项目**: ```c #include "cJSON.h" // 编译时需包含cJSON.c ``` --- ### 三、基础用法示例 #### 1. 创建JSON对象 ```c cJSON *root = cJSON_CreateObject(); // 创建根对象 cJSON_AddStringToObject(root, "name", "张三"); cJSON_AddNumberToObject(root, "age", 28); cJSON *scores = cJSON_CreateArray(); // 创建数组 cJSON_AddItemToArray(scores, cJSON_CreateNumber(95)); cJSON_AddItemToArray(scores, cJSON_CreateNumber(88)); cJSON_AddItemToObject(root, "scores", scores); char *json_str = cJSON_Print(root); // 生成格式化字符串 printf("%s\n", json_str); /* 输出: { "name": "张三", "age": 28, "scores": [95, 88] } */ free(json_str); // 必须手动释放 cJSON_Delete(root); // 释放整个结构 ``` #### 2. 解析JSON字符串 ```c const char *json_data = "{\"status\": true, \"temperature\": 25.6}"; cJSON *root = cJSON_Parse(json_data); if (root == NULL) { const char *error_ptr = cJSON_GetErrorPtr(); printf("解析错误位置: %s\n", error_ptr); return; } cJSON *status = cJSON_GetObjectItemCaseSensitive(root, "status"); if (cJSON_IsBool(status)) { printf("状态: %s\n", status->valueint ? "true" : "false"); } cJSON *temp = cJSON_GetObjectItem(root, "temperature"); if (cJSON_IsNumber(temp)) { printf("温度: %.1f\n", temp->valuedouble); } cJSON_Delete(root); ``` --- ### 四、内存管理要点 1. **创建对象必须释放**: ```c cJSON *obj = cJSON_CreateObject(); // ...使用对象 cJSON_Delete(obj); // 递归释放所有子节点 ``` 2. **字符串输出需单独释放**: ```c char *str = cJSON_Print(root); // 使用字符串... free(str); // 使用cJSON_free释放(实际是标准free) ``` 3. **避免内存泄漏检测方法**: ```bash valgrind --leak-check=full ./your_program ``` --- ### 五、高级操作技巧 #### 1. 处理嵌套结构 ```c // 解析多层JSON const char *complex_json = "{ \"data\": { \"sensors\": [ {\"id\": 1}, {\"id\": 2} ] } }"; cJSON *root = cJSON_Parse(complex_json); cJSON *sensors = cJSON_GetObjectItem( cJSON_GetObjectItem(root, "data"), "sensors" ); cJSON *sensor; cJSON_ArrayForEach(sensor, sensors) { // 遍历数组 cJSON *id = cJSON_GetObjectItem(sensor, "id"); printf("传感器ID: %d\n", id->valueint); } ``` #### 2. 修改已有数据 ```c cJSON *root = cJSON_Parse("{\"count\": 0}"); cJSON *count = cJSON_GetObjectItem(root, "count"); count->valueint = 42; // 直接修改数值 count->valuedouble = 42.0; // 需同时更新两种表示 ``` #### 3. 合并JSON对象 ```c cJSON *obj1 = cJSON_Parse("{\"a\": 1}"); cJSON *obj2 = cJSON_Parse("{\"b\": 2}"); cJSON_AddItemToObject(obj1, "b", cJSON_Duplicate(obj2, 1)); // 结果:{"a":1, "b":2} ``` --- ### 六、错误处理最佳实践 ```c cJSON *root = cJSON_Parse(json_input); if (root == NULL) { fprintf(stderr, "错误前内容: %.*s\n", 20, cJSON_GetErrorPtr() - 20); exit(EXIT_FAILURE); } if (!cJSON_IsObject(root)) { fprintf(stderr, "根元素不是对象\n"); cJSON_Delete(root); return; } ``` --- ### 七、性能优化建议 1. **使用无格式输出**: ```c char *str = cJSON_PrintUnformatted(root); // 无空格节省体积 ``` 2. **重用对象池**: ```c // 对高频创建的对象,使用静态缓存 static cJSON *temp_obj = cJSON_CreateObject(); cJSON_DeleteItemFromObject(temp_obj, ...); // 清空重用 ``` 3. **流式解析(大文件处理)**: ```c FILE *fp = fopen("large.json", "r"); char buffer[4096]; while (fgets(buffer, sizeof(buffer), fp)) { cJSON *partial = cJSON_Parse(buffer); // 处理片段数据... } ``` --- ### 八、常见问题解决 1. **中文乱码问题**: ```c cJSON *item
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值