JSON 数据类型 序列化 反序列化

了解json

        JSON是JavaScript Object Notation的缩写,它是一种数据交换格式。

        在JSON出现之前,大家一直用XML来传递数据。因为XML是一种纯文本格式,所以它适合在网络上交换数据。XML本身不算复杂,但是,加上DTD、XSD、XPath、XSLT等一大堆复杂的规范以后,任何正常的软件开发人员碰到XML都会感觉头大了,最后大家发现,即使你努力钻研几个月,也未必搞得清楚XML的规范。

        终于,在2002年的一天,道格拉斯·克罗克福特(Douglas Crockford)同学为了拯救深陷水深火热同时又被某几个巨型软件企业长期愚弄的软件工程师,发明了JSON这种超轻量级的数据交换格式。

        道格拉斯同学长期担任雅虎的高级架构师,自然钟情于JavaScript。他设计的JSON实际上是JavaScript的一个子集。在JSON中,一共就这么几种数据类型:

  • number:和JavaScript的number完全一致;
  • boolean:就是JavaScript的truefalse
  • string:就是JavaScript的string
  • null:就是JavaScript的null
  • array:就是JavaScript的Array表示方式——[]
  • object:就是JavaScript的{ ... }表示方式。

以及上面的任意组合。并且,JSON还定死了字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号"",Object的键也必须用双引号""

        由于JSON非常简单,很快就风靡Web世界,并且成为ECMA标准。几乎所有编程语言都有解析JSON的库,而在JavaScript中,我们可以直接使用JSON,因为JavaScript内置了JSON的解析。把任何JavaScript对象变成JSON,就是把这个对象序列化成一个JSON格式的字符串,这样才能够通过网络传递给其他计算机。如果我们收到一个JSON格式的字符串,只需要把它反序列化成一个JavaScript对象,就可以在JavaScript中直接使用这个对象了。


json数据类型

  • number:数字型,和JavaScript的number完全一致;包括整型和浮点
  • 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表示。


格式规范

json以大括号起始和结尾

内容都是以键值对的形式存在

所有的键都是字符串

值的类型不一定,属于JavaScript 的基本数据类型

每个键值对以,分割

最后一个键值对不加逗号

{
  "name": "小明",
  "age": 14,
  "gender": true,
  "height": 1.65,
  "grade": null,
  "skills": [
    "JavaScript",
    "Java",
    "Python",
    "Lisp"
  ]
}

该json数据用C语言字符串表示:

 const char* json_string = "{\"name\":\"小明\",\"age\":14,\"gender\":true,\"height\":1.65,\"grade\":null,\"skills\":[\"JavaScript\",\"Java\",\"Python\",\"Lisp\"]}";  

json格式校验

在线JSON校验格式化工具(Be JSON)


JSON基本操作

Json序列化:可以理解为利用程序生成Json字符串的过程。

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


cJson

官方地址

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

https://github.com/DaveGamble/cJSON

📎cJSON.h📎cJSON.c

参考资料

cJSON 使用详解

C语言处理JSON-CSDN博客

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

JSON的简单介绍以及C语言的JSON库使用 - 流年十维 - 博客园

关键接口梳理

/* 类型定义 */
#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的结构(反序列化)
//如果json数据格式不对,则返回空
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 index);
//获取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对象中,添加字符串节点为例:  
#define cJSON_AddStringToObject(object,name,s)\
       cJSON_AddItemToObject(object, name, cJSON_CreateString(s))

该宏方法将创建节点与添加节点这两布合成到了一步,非常好用。
       
与上述类似,还有添加其他数据类型的方法:
cJSON_AddBoolToObject(cJSON *object, const char *string, int value);//不包含C99则bool类型填1或0
cJSON_AddNumberToObject(cJSON *object, const char *string, int value);  
cJSON_AddNullToObject(cJSON *object, const char *string);  //添加NULL无需填写数据

至于添加数组或对象,建议创建cJSON对象节点,再添加到root对象中。

//创建各种类型的cJSON节点
cJSON *cJSON_CreateNull(void);
cJSON *cJSON_CreateTrue(void);
cJSON *cJSON_CreateFalse(void);
cJSON *cJSON_CreateBool(int b);
cJSON *cJSON_CreateNumber(double num);  //这个接口只需要传入整形形参,double会自动强转
cJSON *cJSON_CreateString(const char *string);
cJSON *cJSON_CreateArray(void);
cJSON *cJSON_CreateObject(void);

序列化与反序列化示例

序列化

int main(){
    cJSON* root = cJSON_CreateObject();
    
    cJSON_AddStringToObject(root,"name","小明");
    cJSON_AddNumberToObject(root,"age",14);
    cJSON_AddBoolToObject(root,"gender",1);
    cJSON_AddNumberToObject(root,"height",1.65);
    cJSON_AddStringToObject(root,"grade","");
    
    cJSON *skills = cJSON_CreateArray(); // 数组
    cJSON_AddItemToArray(skills,cJSON_CreateString("JavaScript"));
    cJSON_AddItemToArray(skills,cJSON_CreateString("Java"));
    cJSON_AddItemToArray(skills,cJSON_CreateString("Python"));
    cJSON_AddItemToArray(skills,cJSON_CreateString("Lisp"));
    cJSON_AddItemToObject(root,"skills",skills);
    char* string = cJSON_Print(root);
    printf("%s\n",string);
    cJSON_Delete(root);
    return 0;
}

反序列化

int main(){
    const char* json_string = "{\"name\":\"小明\",\"age\":14,\"gender\":true,\"height\":1.65,\"grade\":null,\"skills\":[\"JavaScript\",\"Java\",\"Python\",\"Lisp\"]}";  
    cJSON* root = cJSON_Parse(json_string);
    if(root == NULL){
        printf("wrong json\n");
        return 0;
    }
    /*name*/
    cJSON* name = cJSON_GetObjectItem(root,"name");
    if(name == NULL){
        printf("wrong name\n");
        return 0;
    }
    if(name->type == cJSON_String){
        printf("name : %s\n",name->valuestring);
    }
    /*age*/
    cJSON* age = cJSON_GetObjectItem(root,"age");
    if(age == NULL){
        printf("wrong age\n");
        return 0;
    }
    if(age->type == cJSON_Number){
        printf("age : %d\n",age->valueint);
    }
    /*gender*/
    cJSON* gender = cJSON_GetObjectItem(root,"gender");
    if(gender == NULL){
        printf("wrong gender\n");
        return 0;
    }
    if(gender->type == cJSON_True){
        printf("gender : true\n");
    }
    else{
        printf("gender : false\n");
    }
    /*height*/
    cJSON* height = cJSON_GetObjectItem(root,"height");
    if(height == NULL){
        printf("wrong height\n");
        return 0;
    }
    if(height->type == cJSON_Number){
        printf("height : %.2f\n",height->valuedouble);
    }
    /*grade*/
    cJSON* grade = cJSON_GetObjectItem(root,"grade");
    if(grade == NULL){
        printf("wrong grade\n");
        return 0;
    }
    if(grade->type == cJSON_Number){
        printf("grade : %d\n",grade->valueint);
    }
    else{
        printf("grade : null\n");
    }
    /*skills*/
    cJSON* skills = cJSON_GetObjectItem(root,"skills");
    int arrar_size = cJSON_GetArraySize(skills);
    if(skills == NULL){
        printf("wrong skills\n");
        return 0;
    }
    cJSON* skill;
    printf("skills : ");
    for(int i = 0;i<arrar_size;i++){
        skill = cJSON_GetArrayItem(skills,i);
        if(skill->type == cJSON_String){
            printf("%s ",skill->valuestring);
        } 
    }
    printf("\n");
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值