cjson

1.JSON格式简述

        JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它使得人们很容易的进行阅读和编写。 同时也方便了机器进行解析和生成。它是基于 JavaScript Programming Language , Standard ECMA-262 3rd Edition - December 1999 的一个子集。 JSON采用完全独立于程序语言的文本格式,但是也使用了类C语言的习惯 包括C, C++, C#, Java, JavaScript, Perl, Python等。这些特性使JSON成为理想的数据交换语言.c语言的json解析器有个开源项目为cjson为本文介绍对象

1.1 json结构

JSON结构从大的方面来将有两种结构: json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构

1、对象:对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,…}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值 所以很容易理解,取值方法为 对象.key 获取属性值,这个属性值的类型可以是 数字、字符串、数组、对象几种。

2、数组:数组在js中是中括号“[]”括起来的内容,数据结构为 [“java”,”javascript”,”vb”,…], 取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种

{
    "animals": {
        "dog": [
            {
                "name": "Rufus",
                "age":15
            },
            {
                "name": "Marty",
                "age": null
            }
        ]
    }
}

1.1 JSON值

cjson_第1张图片

对象(object) 是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

数组(array) 是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。

值(value) 可以是双引号括起来的字符串(string)、数值(number)、truefalse、 null、对象(object)或者数组(array)。这些结构可以嵌套。

字符串(string) 是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符串(character string)。

JSON的字符串(string)与C或者Java的字符串非常相似。

数值(number) 也与C或者Java的数值非常相似。只是JSON的数值没有使用八进制与十六进制格式

2.cJSON介绍

2.1 源码位置

  https://github.com/DaveGamble/cJSON

2.2 格式验证

下面网站有在线验证功能与格式整理,同时能将json转化为对应的xml文件

https://www.json.cn/

2.4 移植相关

由于整个库只有一个C文件和一个头文件,你可以复制cJSON.hcJSON.c到您的项目源,并开始使用它.

其它方法参考  https://github.com/DaveGamble/cJSON里面移植相关的 (PC机使用相当简单,故不描述了)

eg:

1.交叉编译过程

编译:

cjson_第2张图片

安装:

结构:

2.测试:

测试代码为2.5.1片段代码:

(1)编译测试code

(1.1) 发现找不到头文件,这是因为环境变量中没有上面install安装库头文件的位置

解决方案:使用-I或者 C_INCLUDE_PATH

cjson_第3张图片

cjson_第4张图片

(1.2)以上截图缺少符号表,可加入-lcjson

 (1.3)以上截图为xx-ld 无法找到cjson库,-L加入库的位置或者LIBRARY_PATH环境变量

(2)执行二进制文件

将二进制文件下载到开发板中

/a.out: error while loading shared libraries: libcjson.so.1: cannot open shared object file: No such file or directory

这是因为开发板中缺少cjson动态库。

在开发板中输入

root:# ldconfig -p
ldconfig: Can't open cache file /etc/ld.so.cache
: No such file or directory

root@u1-sdr:/etc# chmod 777 ld.so.cache

root@u1-sdr:/etc# ldconfig -p
33 libs found in cache `/etc/ld.so.cache'
libuuid.so.1 (libc6,soft-float) => /lib/libuuid.so.1
libutil.so.1 (libc6,soft-float, OS ABI: Linux 2.6.32) => /lib/libutil.so.1

........

发现坏境库放在/lib,所有可以将交叉编译的cjson库全拷贝开发板中的/lib中

cjson_第5张图片

2.5使用示例

cjson 结构体:

1.cJOSN结构体为一个双向列表,并可通过child指针访问下一层。

2.type变量决定数据项类型(键的类型),数据项可以是字符串可以是整形,也可以是浮点型。

判断:

#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array  (1 << 5)
#define cJSON_Object (1 << 6)

json->type==cJSON_Number
json->type == cJSON_String

取值:

cJSON_GetObjectItem(json, "xx")->valueint
cJSON_GetObjectItem(json, "xx")->valuestring
cJSON_GetObjectItem(json, "xx")->valuedouble;

/* The cJSON structure: */
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;

2.5.1 解析json数据且写入文件

#include
#include
#include 

int main()
{

	char data[] = "{\"name\":\"maketure\",\"age\":20}";
	//json是json对象指针,json_name是 name对象的指针,json_age是age对象的指针
	cJSON *json = 0, *json_name = 0, *json_age = 0;
	//解析数据包
	json = cJSON_Parse(data);
	char*buf = NULL;
	//如果解析失败
	if (!json)
	{
		printf("Error Before:", cJSON_GetErrorPtr());
	}
	else
	{
		json_age = cJSON_GetObjectItem(json, "age");
		//如果类型是 数字
		if (json_age->type == cJSON_Number)
		{

			printf("年龄:%d\n", json_age->valueint);
		}
		json_name = cJSON_GetObjectItem(json, "name");
		//如果类型是 字符串
		if (json_name->type == cJSON_String)
		{
			printf("姓名:%s\n", json_name->valuestring);
		}

	}
	buf = cJSON_Print(json);

	FILE *fp = fopen("test.json", "w");
	fwrite(buf, strlen(buf), 1, fp);

	//释放内存
	cJSON_Delete(json);

	return 0;
}

2.5.2 从json文件中解析json数据

#include
#include
#include 
int main()
{
	//json是json对象指针,json_name是 name对象的指针,json_age是age对象的指针
	cJSON *json = 0, *json_name = 0, *json_age = 0;

	FILE *fp = fopen("test.json", "rb");

	long len;//文件长度
	char *content;//文件内容

	fseek(fp, 0, SEEK_END);
	len = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	content = (char*)malloc(len + 1);
	fread(content, 1, len, fp);
	fclose(fp);

	//解析数据包
	json = cJSON_Parse(content);

	//如果解析失败
	if (!json)
	{
		printf("Error Before:", cJSON_GetErrorPtr());
	}
	else
	{
		json_age = cJSON_GetObjectItem(json, "age");
		//如果类型是 数字
		if (json_age->type == cJSON_Number)
		{

			printf("年龄:%d\n", json_age->valueint);
		}
		json_name = cJSON_GetObjectItem(json, "name");
		//如果类型是 字符串
		if (json_name->type == cJSON_String)
		{
			printf("姓名:%s\n", json_name->valuestring);
		}

	}
	char*buf = NULL;

	cJSON_Delete(json);

	return 0;
}

2.5.3 json数组使用

  1.使用链表方式循环查找

json_attribute = json_get_device_attribute(json, &attribute_size);
attribute_list = json_attribute->child;
int number = cJSON_GetArraySize(json_attribute);

for (i = 0; i < number; i++) {
    temp_id = cJSON_GetObjectItem( attribute_list , "device_id")->valuestring;

    attribute_list = attribute_list->next;
}

 2.利用库函数使用index


{
    "test":[{"ip":1,"msak":2},{"ip":1,"msak":2}]
}

cJSON *json = NULL;
cJSON *attribute_obj = NULL;
cJSON *current_child = NULL;

json = cJSON_Parse(file);
attribute_obj = cJSON_GetObjectItem(json,"test");

current_child = cJSON_GetArrayItem(attribute_obj, index);
temp_id = cJSON_GetObjectItem( current_child , "device_id")->valuestring;

2.6 注意点

1.json不支持十六进制与八进制,若需要表示,则可以写出”0x00”,然后 使用sscanf(第三个参数只能为32bit数据),同时“0x0”这样的格式解析出来不对,sscanf(cJSON_GetObjectItem( blocks_items , "position")->valuestring,   "0x%x", (ConfigData[i].info[j].end));

2.{ "configAttribute": [ {"gear":"1"},],}这样格式错误,若后面没有对象了,不应有“,”存在, sublime在检验这种格式时,就会认为正常。

3.数组还可以表示为{"test":["2222","3444","5555"]}

3.与xml对比

和XML的比较

可读性

JSON和XML的可读性可谓不相上下,一边是简易的语法,一边是规范的标签形式,很难分出胜负。

可扩展性

XML天生有很好的扩展性,JSON当然也有,没有什么是XML可以扩展而JSON却不能扩展的。不过JSON在Javascript主场作战,可以存储Javascript复合对象,有着xml不可比拟的优势。

编码难度

XML有丰富的编码工具,比如Dom4j、JDom等,JSON也有提供的工具。无工具的情况下,相信熟练的开发人员一样能很快的写出想要的xml文档和JSON字符串,不过,xml文档要多很多结构上的字符。

解码难度

  • XML的解析方式有两种:
  • 一是通过文档模型解析,也就是通过父标签索引出一组标记。例如:xmlData.getElementsByTagName("tagName"),但是这样是要在预先知道文档结构的情况下使用,无法进行通用的封装。
  • 另外一种方法是遍历节点(document 以及 childNodes)。这个可以通过递归来实现,不过解析出来的数据仍旧是形式各异,往往也不能满足预先的要求。

凡是这样可扩展的结构数据解析起来一定都很困难。

JSON也同样如此。如果预先知道JSON结构的情况下,使用JSON进行数据传递简直是太美妙了,可以写出很实用美观可读性强的代码。如果你是纯粹的前台开发人员,一定会非常喜欢JSON。但是如果你是一个应用开发人员,就不是那么喜欢了,毕竟xml才是真正的结构化标记语言,用于进行数据传递。

而如果不知道JSON的结构而去解析JSON的话,那简直是噩梦。费时费力不说,代码也会变得冗余拖沓,得到的结果也不尽人意。但是这样也不影响众多前台开发人员选择JSON。因为json.js中的toJSONString()就可以看到JSON的字符串结构。当然不是使用这个字符串,这样仍旧是噩梦。常用JSON的人看到这个字符串之后,就对JSON的结构很明了了,就更容易的操作JSON。

以上是在Javascript中仅对于数据传递的xml与JSON的解析。在Javascript地盘内,JSON毕竟是主场作战,其优势当然要远远优越于xml。如果JSON中存储Javascript复合对象,而且不知道其结构的话,我相信很多程序员也一样是哭着解析JSON的。

除了上述之外,JSON和XML还有另外一个很大的区别在于有效数据率。JSON作为数据包格式传输的时候具有更高的效率,这是因为JSON不像XML那样需要有严格的闭合标签,这就让有效数据量与总数据包比大大提升,从而减少同等数据流量的情况下,网络的传输压力。

你可能感兴趣的:(三方库移植与使用)