JSON构造/解析(by C)---cJSON和json-c

背景

JSON即JavaScript Object Notation,是一种轻量级的数据交换格式。

JSON建构于两种结构:

  • “名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
  • 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

关于JSON库的性能评测与标准符合程度,可以参照《28 个 C/C++ 开源 JSON 程序库性能及标准符合程度评测》,另一个英文版更详细结果在nativejson-benchmark

在阅读了一系列评测之后,结合需求(ROM尽量小,RAM尽量小,带处理的数据比较简单),准备研究一下cJSON和json-c。

JSON官网获得json-c和cJSON的源码地址如下:cJSONjson-c

下面就基于这两份代码在Ubuntu进行速度和兼容性测试。

测试标的构造对于测试的覆盖以及测试有效性非常重要,所幸的在AOSP中有一个参考AOSP/external/jsoncpp/test。

cJSON

下载代码:

git clone https://github.com/arnoldlu/cJSON.git

编译安装:

mkdir build
cd build
cmake .. -DENABLE_CJSON_UTILS=Off -DENABLE_CJSON_TEST=On -DCMAKE_INSTALL_PREFIX=/usr (生成bin+lib)
cmake .. -DENABLE_CJSON_UTILS=Off -DENABLE_CJSON_TEST=On -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=Off (生成bin)
make
sudo make install (安装libcjson.so)

使用实例

参考文档:《使用 CJSON 在C语言中进行 JSON 的创建和解析的实例讲解》、《cJSON学习笔记》。

下面是一个构造JSON数据,然后解析,打印Type-Key-Value的小示例:

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

void printJson(cJSON *root)
{
    if(!root)
    {
        printf("NULL JSON root. ");
        return;
    }
   
    printf("Type=0x%02x, %s=%s ", root->type, root->string, cJSON_Print(root));  cJSON_Print会根据类型打印
}

static char * makeJson(void)
{
    cJSON *pJsonRoot = NULL;
    cJSON *pSubJson = NULL;
    char *p = NULL;

    pJsonRoot = cJSON_CreateObject();
    if(NULL == pJsonRoot)
    {
        printf("%s line=%d NULL ", __func__, __LINE__);
        return NULL;
    }
    cJSON_AddStringToObject(pJsonRoot, "hello", "hello world");  String类型
    cJSON_AddNumberToObject(pJsonRoot, "number", 10010);  Number类型
    cJSON_AddBoolToObject(pJsonRoot, "bool", 1);  bool类型
    pSubJson = cJSON_CreateObject();  建一个cJSON,用于嵌套数据
    if(NULL == pSubJson)
    {
        printf("%s line=%d NULL ", __func__, __LINE__);
        cJSON_Delete(pJsonRoot);
        return NULL;
    }
    cJSON_AddStringToObject(pSubJson, "subjsonobj", "a sub json string");  在子cJSON下,增加一个String类型数据
    cJSON_AddItemToObject(pJsonRoot, "subobj", pSubJson);  将子cJSON加入到pJsonRoot

    p = cJSON_Print(pJsonRoot);
    if(NULL == p)
    {
        printf("%s line=%d NULL ", __func__, __LINE__);
        cJSON_Delete(pJsonRoot);
        return NULL;
    }

    cJSON_Delete(pJsonRoot);

    return p;
}


static void parseJson(char * pMsg)
{
    cJSON *pJson;
    cJSON *pSub;
    cJSON * pSubSub;

    if(NULL == pMsg)
    {
    return;
    }

    pJson = cJSON_Parse(pMsg);
    if(NULL == pJson)                                                                                        
    {
        return ;
    }

    pSub = cJSON_GetObjectItem(pJson, "hello");
    printJson(pSub);

    pSub = cJSON_GetObjectItem(pJson, "number");
    printJson(pSub);

    pSub = cJSON_GetObjectItem(pJson, "bool");
    printJson(pSub);

    pSub = cJSON_GetObjectItem(pJson, "subobj");
    printJson(pSub);

    pSubSub = cJSON_GetObjectItem(pSub, "subjsonobj");
    printJson(pSubSub);

    cJSON_Delete(pJson);
}

int main(void)
{
    char *p;

    /* print the version */
    printf("Version: %s ", cJSON_Version());  获取cJSON版本号

    p = makeJson();  构造JSON数据
    if(NULL == p)
    {
        return 0;
    }
    printf("p = %s ", p);  打印构造的字符串
    parseJson(p);  解析JSON数据,并打印Type-Key-Value
    free(p);
    return 0;
}

在安装(sudo make install)cJSON之后,编译的时候需要跟上libcjson库文件:

gcc demo.c -o demo -lcjson

执行结果如下:

Version: 1.3.2
p =
{
    "hello":    "hello world",
    "number":    10010,
    "bool":    true,
    "subobj":    {
        "subjsonobj":    "a sub json string"
    }
}

Type=0x10, hello="hello world"
Type=0x08, number=10010
Type=0x02, bool=true
Type=0x40, subobj={
    "subjsonobj":    "a sub json string"
}
Type=0x10, subjsonobj="a sub json string"

json-c

参考文档:《JSON C库的使用

下载代码:

git clone https://github.com/arnoldlu/json-c.git

编译安装:

sh autogen.sh
./configure
make
make install
原文地址:https://www.cnblogs.com/arnoldlu/p/6490860.html