cJSON 笔记

最近工作中用到了一个叫 cJSON 的轻量级 JSON 解析器,感觉挺好用的,就做个笔记记录一下。

1 概述

cJSON 是一个轻量级的开源 JSON 解析器,它使用的是 ANSI C 标准,LICENSE 是 MIT。

github 地址在: https://github.com/DaveGamble/cJSON

使用方法很简单,直接把项目下的cJSON.ccJSON.h文件拷贝出来就行了,所有的解析方法和结构体都在这两个文件里,名副其实的轻量级:)。

在头文件中:

1
#include "cJSON.h"

不嫌麻烦也可以 make 一下,

1
2
3
4
5
$ mkdir build
$ cd build
$ cmake ..
$ make
$ make install

make 后,安装完,会将头文件安装到/usr/local/include/cjson将库安装到/usr/local/lib,同样 include 一下。

1
#include <cjson/cJSON.h>

2 结构体

cJSON 中将 json 数据抽象成结构体cJSON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
typedef struct cJSON
{
    /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
    struct cJSON *next;
    struct cJSON *prev;
    /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
    struct cJSON *child;

    /* The type of the item, as above. */
    int type;

    /* The item's string, if type==cJSON_String  and type == cJSON_Raw */
    char *valuestring;
    /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
    int valueint;
    /* The item's number, if type==cJSON_Number */
    double valuedouble;

    /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
    char *string;
} cJSON;

可以看到,在 cJSON 中将 json 中的 value 粗糙地分成了三种类型valuestringvalueintvaluedouble,不过这三种类型已经能够满足绝大多数需求。json 的 key 使用string表示。

type使用了一个比特位来表示接收到的不同数据类型

1
2
3
4
5
6
7
8
9
10
11

/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False  (1 << 0)
#define cJSON_True   (1 << 1)
#define cJSON_NULL   (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array  (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw    (1 << 7) /* raw json */

结合type可以判断更多的数据类型,包括 bool 值。使用cJSON_is...方法来判断是否为对应类型。

对应cJSON_is...方法判断类型,可以使用cJSON_Create...方法创建对应的类型,返回一个对应类型的cJSON

3 解析 JSON

解析一个以 0 结尾的 JSON 字符串,直接使用cJSON_Parse

1
cJSON *json = cJSON_Parse(string);

这个方法会解析 string,并且生成一颗cJSON树。使用完后要使用cJSON_Delete释放它。

获得 cJSON 结构体之后,就可以对结构体做各种相应的操作了,比如cJSON_GetObjectItemcJSON_GetObjectItemCaseSensitive从 child 里面找一个固定 string 的 cJSON。

1
2
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)

cJSON_HasObjectItem判断 json 中是否有对应 string 的项。

cJSON 提供三个方面的方法:解析 json、组合 json、打印 json,具体内容查看 cJSON.h 头文件就一目了然了。

4 解析对照图

以官网的字符串为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
    "name": "Awesome 4K",
    "resolutions": [
        {
            "width": 1280,
            "height": 720
        },
        {
            "width": 1920,
            "height": 1080
        },
        {
            "width": 3840,
            "height": 2160
        }
    ]
}

解析后,在内存结构体中如图:cJSON

c'JSON