欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JSON详解

程序员文章站 2022-03-10 08:04:06
...

本文部分借鉴 阿阿阿阿阿阿鑫 的博客,特此说明。
https://blog.csdn.net/fengxinlinux/article/details/53121287

一.JSON格式简述

JSON(JavaScriptObject Notation, JS 对象标记) 是一种轻量级的数据交换格式,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
cJSON从名字可知,整个项目都是以极标准的C来写的,意思说,可以跨各种平台使用了。cJSON是一个超轻巧,携带方便,单文件,简单的可以作为ANSI-C标准的JSON解析器。

二.cJSON结构体

typedef struct cJSON {  
 struct cJSON *next,*prev;   
 struct cJSON *child;   
 int type;   
 char *valuestring;   
 int valueint;  
 double valuedouble;   
 char *string;   
} cJSON;  

说明1.cJSON是使用链表来存储数据的,其访问方式很像一颗树。每一个节点可以有兄弟节点,通过next/prev指针来查找,它类似双向链表;每个节点也可以有孩子节点,通过child指针来访问,进入下一层。只有节点是对象或数组时才可以有孩子节点。

说明2.type是键(key)的类型,一共有7种取值,分别是:False,Ture,NULL,Number,String,Array,Object。若是Number类型,则valueint或valuedouble中存储着值。若期望的是int,则访问valueint,若期望的是double,则访问valuedouble,可以得到值。若是String类型的,则valuestring中存储着值,可以访问valuestring得到值

说明3.string中存放的是这个节点的名字,可理解为key的名称。

说明4.cJSON作为Json格式的解析库,其主要功能无非就是构建和解析Json格式了,用途就是一端将要发送的数据已cjson形式封装,然后发送,另一端收到此数据后,还是按cjson形式解析,就得到想要的数据了。

三.封装为JSON格式

3.1 创建一个对象,并向这个对象里添加字符串和整型键值
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include"cJSON.h"
    int main()
    {
            cJSON * usr;
            cJSON *arry;
            usr=cJSON_CreateObject();   //创建根数据对象
            cJSON_AddStringToObject(usr,"name","fengxin");  //加入键值,加字符串
            cJSON_AddStringToObject(usr,"passwd","123");
            cJSON_AddNumberToObject(usr,"num",1);  //加整数

            char *out = cJSON_Print(usr);   //将json形式打印成正常字符串形式
            printf("%s\n",out);

            // 释放内存  
            cJSON_Delete(usr);  
            free(out);    
    }

    运行结果:
    {
    "name": "fengxin",
    "passwd":   "123",
    "num":  1
    }

    API说明:
    1.cJSON_CreateObject函数可创建一个根数据项,之后便可向该根数据项中添加string或int等内容,返回的是一个 cJSON的指针,注意,在这个指针用完了以后,需要手工调用 cJSON_Delete(root); 进行内存回收。因为内部malloc申请了内存
    2.cJSON_AddNumberToObject向节点中添加子节点,例如此处添加name节点,节点值为字符串"fengxin"
    3.需要注意的是  json 格式的数据,虽然也是一个字符串的样子,但这个时候还是无法当成普通的字符串进行使用,需要调用 cJSON_PrintUnformatted(root) 或者 cJSON_Print(root);来将json对象转换成普通的字符串,并且都是以该json对象的根为基点。两个API的区别即是:一个是没有格式的:也就是转换出的字符串中间不会有"\n" "\t"之类的东西存在,而cJSON_Print(root);打印出来是人看起来很舒服的格式。
    4.因为函数内部封装有malloc函数,所以使用free函数释放被out占用的内存空间
3.2 创建一个数组,并向数组添加一个字符串和一个数字:
        int create_js(void)
        {
            cJSON *root, *js_body;
            root = cJSON_CreateArray();
            cJSON_AddItemToArray(root, cJSON_CreateString("Hello world"));
            cJSON_AddItemToArray(root, cJSON_CreateNumber(10)); 
            {
                char *s = cJSON_PrintUnformatted(root);
                if(s){
                   printf(" %s \n",s);
                    free(s);
                }
            }
            if(root)
            cJSON_Delete(root);

            return 0;

        }

        int main(int argc, char **argv)
        {
            create_js();
            return 0;
        }

        运行结果:
        ["Hello world",10]
3.3 对象里面包括一个数组,数组里面包括对象,对象里面再添加一个字符串和一个数字:
        int create_js(void)
    {
        cJSON *root, *js_body, *js_list;
        root = cJSON_CreateObject();
        cJSON_AddItemToObject(root,"body", js_body = cJSON_CreateArray());
        cJSON_AddItemToArray(js_body, js_list = cJSON_CreateObject());
        cJSON_AddStringToObject(js_list,"name","fengxin");
        cJSON_AddNumberToObject(js_list,"status",100);

        {
            char *s = cJSON_PrintUnformatted(root);
            if(s){
                printf(" %s \n",s);
                free(s);
            }
        }
        if(root)
            cJSON_Delete(root);

        return 0;
    }

    int main(int argc, char **argv)
    {
        create_js();
        return 0;
    }

    运行结果:
    {"body":[{"name":"fengxin","status":100}]}

四.解析JSON格式包得到数据

4.1 首先将普通的json串处理成json对象
    cJSON *root;
root = cJSON_Parse(js_string);
4.2 取关键字之无父层次,但如果关键字还有父层或者祖层,那就需要先从父层开拿,剥洋葱一样:
out={\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}

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

int main()
{
    cJSON *json,*json_name,*json_passwd,*json_num;
    char* out="{\"name\":\"fengxin\",\"passwd\":\"123\",\"num\":1}";

    json = cJSON_Parse(out); //解析成json形式
    json_name = cJSON_GetObjectItem( json , "name" );  //获取键值内容
    json_passwd = cJSON_GetObjectItem( json , "passwd" );
    json_num = cJSON_GetObjectItem( json , "num" );

    printf("name:%s,passwd:%s,num:%d\n",json_name->valuestring,json_passwd->valuestring,json_num->valueint);

    cJSON_Delete(json);  //释放内存 
    free(out);
}

运行结果:
name:fengxin,passwd:123,num:1
4.3 取关键字之有父层次
out={\"list\":{\"name\":\"hahaha\"}}

    char *s = "{\"list\":{\"name\":\"hahaha\"}}";
        cJSON *root = cJSON_Parse(s); //解析成json形式
        cJSON *js_list = cJSON_GetObjectItem(root, "list");//获取键值(节点值)
        cJSON *name = cJSON_GetObjectItem(js_list, "name");
        printf("name is %s\n",name->valuestring);

        if(root){
            cJSON_Delete(root);
                return 0;
            }

        结果:
        name is xiao hong