使用cJSON创建JSON字符串

使用cJSON创建JSON字符串

    在Linux下,使用C语言编程,开始JSON字符串的创建。我们还是一步步来,逐渐由简单到复制。  

1,下载源码

可以从如下网站来下载:https://sourceforge.net/projects/cjson/ 。

2,包含cJSON的源码

下载下来,解压后,从里面找到两个文件(cJSON.c、cJSON.h),复制到我们的工程里面。只需在函数中包含头文件(#include “cJSON.h”),然后和cJSON.c一起编译即可使用。

3,创建一个键值对

         首先是一个简单的键值对字符串,要生成的目标如下:

{"firstName":"Brett"}

要进行创建,就是先确定键与值,然后转为cJSON格式。我们很容易就能明确键为firstName,值为Brett,可是,使用cJSON怎么创建呢? 

对于这个简单的例子,我们需要调用cJSON的五个接口函数就可以实现创建了。(有人不乐意了:都五个函数了,你还说“就可以了”----其实是一法通,百法通,学会了这个创建,其他的创建动作都是非常类似的。)

这五个函数的原型如下:

cJSON*cJSON_CreateObject ();
cJSON*cJSON_CreateString(const char *string);
voidcJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
voidcJSON_Delete(cJSON *c);
char*cJSON_Print(cJSON *item); 

下面按创建过程来描述一次:

(1)       首先调用cJSON_ CreateObject ()函数,创建一个JSON对象,之后便可向这个对象中添加string或int等内容的数据项了。使用该函数会通过malloc()函数在内存中开辟一个空间,使用完成需要手动释放。

        cJSON*root=cJSON_CreateObject();

(2)       调用cJSON_CreateString ()函数,由一个字符串生成一个cJSON的数据项。

        cJSON*item=cJSON_CreateString("Brett");

(3)       将上一步生成的数据项与其键值("firstName")一起添加到root对象中。

        cJSON_AddItemToObject(root,"firstName",item);

其实到这一步,我们在内存中的cJSON对象就已经构建完成了,后面是展示结果了。

(4)       将cJSON对象的内容解析为字符串,并展示出来。

        out=cJSON_Print(root);

        printf("out:%s\n",out);

(5)       通过cJSON_Delete(),释放cJSON_CreateObject ()分配出来的内存空间。

        cJSON_Delete(root);

(6)       释放cJSON_Print ()分配出来的内存空间。

        free(out); 

         这样就完成了一次cJSON接口调用,实现了字符串的创建工作。

4,转换一个结构体 

接下来,我们来个复杂一点的,将一个结构体转换为JSON字符串,结构体定义如下:

typedefstruct
{
         char firstName[32];
         char lastName[32];
         char email[64];
         int age;
         float height;
} PERSON;

看起来比一个键值对复杂多了,我们又需要学习新的接口函数了吗?

是的,由于出现了数字,我们需要学习一个新函数:

cJSON *cJSON_CreateNumber(double num);

当然,创建的步骤要更复杂一些,下面我仍然是按创建过程来描述一次: 

(1)还是先调用cJSON_ CreateObject ()函数,创建一个JSON对象root,做为根(咱们可以把JSON串看成是一颗树)。使用该函数会通过malloc()函数在内存中开辟一个空间,使用完成需要手动释放。

        cJSON*root=cJSON_CreateObject();

(2)继续调用cJSON_ CreateObject ()函数,创建一个JSON对象obj_person,做为挂载结构体内容的对象。挂载内容之后,这个对象是要挂载到根上的。

        cJSON*obj_person=cJSON_CreateObject();

(3)根据数据生成cJSON格式的数据项,调用cJSON_AddItemToObject()函数挂载到obj_person对象上。这个过程,要多次重复,直到将所有数据都添加上。此时要注意,不同的成员,生成的方法是不一样的。

        cJSON*item=cJSON_CreateString(person->firstName);
        cJSON_AddItemToObject(obj_person,"firstName",item);
        item=cJSON_CreateString(person->lastName);
        cJSON_AddItemToObject(obj_person,"lastName",item);
        item=cJSON_CreateString(person->email);
        cJSON_AddItemToObject(obj_person,"email",item);
        item=cJSON_CreateNumber(person->age);
        cJSON_AddItemToObject(obj_person,"age",item);
        item=cJSON_CreateNumber(person->height);
        cJSON_AddItemToObject(obj_person,"height",item);

(4)将obj_person对象挂载到根上。

        cJSON_AddItemToObject(root,"person",obj_person);

到这一步,我们在内存中的cJSON对象就已经构建完成了,后面就是展示结果。

(5)将cJSON对象的内容解析为字符串,并展示出来。

        out=cJSON_Print(root);
        printf("out:%s\n",out);

(6)通过cJSON_Delete(),释放cJSON_CreateObject ()分配出来的内存空间。这里说明一下,我们前面调用了2次cJSON_CreateObject (),最后只需要针对root调用一次释放即可,因为第二次创建的对象也是挂接在root上的。

        cJSON_Delete(root);

(7)释放cJSON_Print ()分配出来的内存空间。

        free(out); 

         至此,我们就使用cJSON接口完成了由结构体生成JSON字符串的工作。 

5,创建结构体数组的JSON串   

         最后,我们来个更复杂一些的,来转换一个数组,并且数组的成员是结构体!我们要生成的目标如下:

{
"people":[
{"firstName":"z","lastName":"Jason","email":"bbbb@126.com","height":1.67},
{"lastName":"jadena","email":"jadena@126.com","age":8,"height":1.17},
{"email":"cccc@126.com","firstName":"z","lastName":"Juliet","age":36,"height":1.55}
]
} 

此时,我们又需要学习新的接口了,一个是创建数组,一个是取数组成员,函数原型如下:

cJSON*cJSON_CreateArray(void);
void   cJSON_AddItemToArray(cJSON *array, cJSON*item); 

由于前面已经实现了单个结构体的转换,这里我们重点关注下数组的相关调用。 

(1)还是先调用cJSON_ CreateObject ()函数,创建一个JSON对象root,做为根。

(2)调用cJSON_CreateArray ()函数,创建一个JSON数组对象,准备挂载多个结构体对象。挂载内容之后,这个数组对象是要挂载到根上的。

        cJSON*array_person=cJSON_CreateArray();

(3)生成一个结构体对象,并相应添加数据,然后调用cJSON_AddItemToArray()函数挂载到数组对象上。这个过程,要多次重复,直到将所有结构体对象都添加上。

        cJSON_AddItemToArray(array_person,obj_person);

(4)将数组对象挂载到根上。

        cJSON_AddItemToObject(root,"people",array_person);

到这一步,我们在内存中的cJSON对象就已经构建完成了。

(5)将cJSON对象的内容解析为字符串,并展示出来。

(6)通过cJSON_Delete(),释放cJSON_CreateObject ()分配出来的内存空间。

(7)释放cJSON_Print ()分配出来的内存空间。

         这样,我们就使用cJSON接口完成了将结构体数组转换成JSON字符串的工作。

详细代码见后文附带例程。         

说明:

本文所附带例程,实现了结构体数组生成JSON字符串,只是一个学习之作,对于初学cJSON的同学,可以有些借鉴参考的作用。 

附带例程:

#include <stdio.h> 
#include <string.h> 
#include <sys/types.h> 
#include <stdlib.h> 
#include <unistd.h> 
 
#include "cJSON.h" 
 
typedef struct 
{  
 int id;  
 char firstName[32];  
 char lastName[32];  
 char email[64];  
 int age;  
 float height;  
}people;  
 
void dofile(char *filename);/* Read a file, parse, render back, etc. */ 
 
int main(int argc, char **argv)  
{  
 
    dofile("json_str4.txt");  
 
 return 0;  
}  
 
 
//create a key-value pair 
int str_to_cJSON(char *json_string, char *str_val)  
{  
 char * out=NULL;  
    cJSON *root=cJSON_CreateObject();  
 if (!root)  
    {  
        printf("Error before: [%s]\n",cJSON_GetErrorPtr());  
 return -1;  
    }  
 else 
    {  
        cJSON *item=cJSON_CreateString("Brett");  
        cJSON_AddItemToObject(root,"firstName",item);  
 
        out=cJSON_Print(root);  
        printf("out2:%s\n",out);  
 
        cJSON_Delete(root);  
 if(out!=NULL)  
        {  
            free(out);  
        }  
    }  
 return 0;  
}  
 
//create a object from struct 
int struct_to_cJSON(char *json_string, people *person)  
{  
 
 if((json_string==NULL) || (person==NULL))  
    {  
        printf("%s: input is invalid",__func__);  
    }  
 
 char * out=NULL;  
    cJSON *root=cJSON_CreateObject();  
 
 if (!root)  
    {  
        printf("Error before: [%s]\n",cJSON_GetErrorPtr());  
 return -1;  
    }  
 else 
    {  
        cJSON *obj_person=cJSON_CreateObject();  
 
        cJSON *item=cJSON_CreateString(person->firstName);  
        cJSON_AddItemToObject(obj_person,"firstName",item);  
 
        item=cJSON_CreateString(person->lastName);  
        cJSON_AddItemToObject(obj_person,"lastName",item);  
 
        item=cJSON_CreateString(person->email);  
        cJSON_AddItemToObject(obj_person,"email",item);  
 
        item=cJSON_CreateNumber(person->age);  
        cJSON_AddItemToObject(obj_person,"age",item);  
 
        item=cJSON_CreateNumber(person->height);  
        cJSON_AddItemToObject(obj_person,"height",item);  
 
        cJSON_AddItemToObject(root,"person",obj_person);  
 
        out=cJSON_Print(root);  
        printf("out2:%s\n",out);  
 
        cJSON_Delete(root);  
 if(out!=NULL)  
        {  
            memcpy(json_string,out,strlen(out));  
            free(out);  
        }  
    }  
 
 return 0;  
}  
 
 
//a struct array to CJSON 
int struct_array_to_cJSON(char *text, people worker[])  
{  
    cJSON *json,*arrayItem,*item,*object;  
 int i;  
 
 for(i=0;i<3;i++)  
    {  
        printf("i=%d, firstName=%s,lastName=%s,email=%s,age=%d,height=%f\n",  
                i,  
                worker[i].firstName,  
                worker[i].lastName,  
                worker[i].email,  
                worker[i].age,  
                worker[i].height);  
    }  
 
 if((text==NULL) || (worker==NULL))  
    {  
        printf("%s: input is invalid",__func__);  
    }  
 
 char * out=NULL;  
    cJSON *root=cJSON_CreateObject();  
 
 if (!root)  
    {  
        printf("Error before: [%s]\n",cJSON_GetErrorPtr());  
 return -1;  
    }  
 else 
    {  
        cJSON *array_person=cJSON_CreateArray();  
 
 for(i=0;i<3;i++)  
        {  
            cJSON *obj_person=cJSON_CreateObject();  
 
            cJSON *item=cJSON_CreateString(worker[i].firstName);  
            cJSON_AddItemToObject(obj_person,"firstName",item);  
 
            item=cJSON_CreateString(worker[i].lastName);  
            cJSON_AddItemToObject(obj_person,"lastName",item);  
 
            item=cJSON_CreateString(worker[i].email);  
            cJSON_AddItemToObject(obj_person,"email",item);  
 
            item=cJSON_CreateNumber(worker[i].age);  
            cJSON_AddItemToObject(obj_person,"age",item);  
 
            item=cJSON_CreateNumber(worker[i].height);  
            cJSON_AddItemToObject(obj_person,"height",item);  
 
            cJSON_AddItemToArray(array_person,obj_person);  
        }  
 
        cJSON_AddItemToObject(root,"people",array_person);  
 
        out=cJSON_Print(root);  
        printf("out:%s\n",out);  
 
        cJSON_Delete(root);  
 if(out!=NULL)  
        {  
            memcpy(text,out,strlen(out));  
            free(out);  
        }  
    }  
 
 return 0;  
}  
 
// create CJSON, write file 
void dofile(char *filename)  
{  
 FILE *f;  
 int len;  
 char data[1024];  
 
    f=fopen(filename,"wb");  
    fseek(f,0,SEEK_END);  
    len=ftell(f);  
    fseek(f,0,SEEK_SET);  
 
    printf("read file %s complete, len=%d.\n",filename,len);  
 
//  char str_name[40]; 
//  int ret = str_to_cJSON(data, str_name); 
 
    people worker[3]={  
            {0,"zhong","Jason","bbbb@126.com",0,1.67},  
            {1,"","jadena","jadena@126.com",8,1.17},  
            {2,"zhu","Juliet","cccc@126.com",36,1.55}  
    };  
//  struct_to_cJSON(data, &worker[1]); 
    struct_array_to_cJSON(data, worker);  
 
    fwrite(data,1,strlen(data),f);  
    fclose(f);  
 
} 

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据结构与算法

BZOJ2438: [中山市选2011]杀人游戏(tarjan)

当然有一种例外情况是\(1 -> 3, 2 -> 3\),也就是存在一个孤立点,判掉即可

12220
来自专栏函数式编程语言及工具

Akka(24): Stream:从外部系统控制数据流-control live stream from external system

 在数据流应用的现实场景中常常会遇到与外界系统对接的需求。这些外部系统可能是Actor系统又或者是一些其它类型的系统。与这些外界系统对接的意思是在另一个线程...

247100
来自专栏码匠的流水账

聊聊hibernate的hbm2ddl的实现

hibernate-core-5.0.12.Final-sources.jar!/org/hibernate/tool/schema/spi/SchemaMan...

10630
来自专栏古时的风筝

模拟实现Spring中的注解装配

在Spring中,XML文件中的bean配置是实现Spring IOC的核心配置文件,在早版本的Spring中,只能基于XML配置文件,配置各个对象之间的依赖关...

23950
来自专栏草根专栏

使用xUnit为.net core程序进行单元测试(中)

第一部分: https://cloud.tencent.com/developer/article/1019835

27680
来自专栏菩提树下的杨过

mybatis的物理分页:mybatis-paginator

文件分割与合并是一个常见需求,比如:上传大文件时,可以先分割成小块,传到服务器后,再进行合并。很多高大上的分布式文件系统(比如:google的GFS、taoba...

23690
来自专栏机器人网

ABB机器人编程方式

1、指令表IL   指令表(IL)由一系列指令组成。每条指令都由一个新行开始,包含一个操作符以及和操作符类型相关的一个或多个操作数,并用逗号分开。在指令前可以有...

37860
来自专栏Golang语言社区

Golang中time包用法--转

time包中包括两类时间:时间点(某一时刻)和时常(某一段时间) 1时间常量(时间格式化) const ( ANSIC = "Mon Jan...

1.7K80
来自专栏更流畅、简洁的软件开发方式

我的数据访问函数库的源代码(三)——返回结构数组

/* 2008 4 25 更新 */ 我的数据访问函数库的源码。整个类有1400行,原先就是分开来写的,现在更新后还是分开来发一下吧。 第三部分:返回结构 ...

21360
来自专栏LhWorld哥陪你聊算法

Hadoop源码篇---解读Mapprer源码outPut输出

上次讲完MapReduce的输入后,这次开始讲MapReduce的输出。注意MapReduce的原语很重要:

15130

扫码关注云+社区

领取腾讯云代金券