1.4 cJSON中的基本数据类型
和编程语言一样,cJSON中也同样的定义了很多数据类型,而且这些类型都是在实际开发中都100%会用到的数据类型。那么对于cJSON来说,它内部有以下这些数据类型:
数字类型(包括整形,单精度浮点数和双精度浮点数类型)
bool类型(cJSON封装了自定义的cJSON_bool类型)
字符串类型
JSON Object类型(JSON的某一个字段的值可以是另一个JSON串,所以有这种Object类型)
RAW类型(这种RAW类型实际上就是原始的JSON串类型,可以将这种类型的数据作为cJSON的Item结点来使用)
空类型(实际上就是NULL类型,在实际开发过程中的网页前后端交互时,后端返回的JSON串就有可能某些字段的值就是空,也就是这个类型)
引用类型
数组类型(可以是整形数组,可以是浮点数组[float或double数组],还可以是字符串数组)
通过一个详细的案例来学习并认识一下如何在cJSON中创建并使用这些数据类型
#include <iostream>
#include "cJSON.h"
using namespace std;
/*!
* 本节将重点介绍cJSON中的几种常用的数据类型以及如何使用cJSON内置的创建函数来创建这些数据类型对应的cJSON Item对象,cJSON里面有以下的几种类型
* 整形类型
* 浮点类型
* bool类型(cJSON是C语言写的,本来是没有bool类型的,但是它内部自己封装了一个cJSON_bool类型
* 字符串类型
* 数组类型(可以是整形数组,可以是浮点数组,可以是字符串数组)
* JSON Object类型(JSON串和JSON串之间是可以嵌套的,那么这种类型相当于还是JSON类型)
* raw类型(JSON原始串类型,可以将一个char*的JSON串作为JSON对象的类型传入到另一个JSON上下文中)
* 空类型(NULL类型,在有些网页后端返回的JSON串中有NULL这种值,那么实际上就是这个玩意)
* 引用类型
*/
void ShowValue(cJSON* item)
{
char* ptr = NULL;
switch (item->type)
{
case cJSON_Invalid:
break;
case cJSON_False:
cout << "As Bool Type Is False" << endl;
break;
case cJSON_True:
cout << "As Bool Type Is True" << endl;
break;
case cJSON_NULL:
cout << "As NULL Type Is NULL" << endl;
break;
case cJSON_Number:
cout << "As Double Number Is " << item->valuedouble << endl;
cout << "As Int Number Is " << item->valueint << endl;
break;
case cJSON_String:
cout << "As String Is " << item->valuestring << endl;
break;
case cJSON_Array:
ptr = cJSON_PrintUnformatted(item);
cout << "As Array Type Is " << ptr << endl;
free(ptr);
ptr = NULL;
break;
case cJSON_Object:
ptr = cJSON_PrintUnformatted(item);
cout << "As cJSON Object Is " << ptr << endl;
free(ptr);
ptr = NULL;
break;
case cJSON_Raw:
ptr = cJSON_PrintUnformatted(item);
cout << "As RAW JSON Is" << ptr << endl;
free(ptr);
ptr = NULL;
break;
case cJSON_IsReference:
break;
case cJSON_StringIsConst:
break;
default:
break;
}
return;
}
int main()
{
//1.cJSON中数字类型的创建和使用
///实际上在cJSON中为了统一性和兼容最大的数据类型的原则,并没有专门创建Int类型的创建函数,只有Number类型(本质就是double类型)
cJSON*piItem = cJSON_CreateNumber(3.1415926);//创建一个叫做PI的Item节点的变量
ShowValue(piItem);
cJSON_Delete(piItem);//创建了对应的数据类型的Item并且使用完毕之后必须调用cJSON_Delete进行释放
piItem = NULL;
//2.cJSON中布尔类型的创建和使用
cJSON*trueItem = cJSON_CreateTrue();
cJSON* falseItem = cJSON_CreateFalse();
ShowValue(trueItem);
ShowValue(falseItem);
cJSON_Delete(trueItem);
cJSON_Delete(falseItem);
trueItem = NULL;
falseItem = NULL;
//3.cJSON中string类型的创建和使用
cJSON* strItem = cJSON_CreateString("LBXXPointer");
ShowValue(strItem);
cJSON_Delete(strItem);
strItem = NULL;
//4.cJSON中Object类型的创建和使用
cJSON* object = cJSON_Parse("{\"Name\":\"LBXXPointer\"}");
ShowValue(object);
cJSON_Delete(object);
object = NULL;
//5.cJSON中RAW类型的创建和使用
const char* rawJSON = "{\"Name\":\"XIAOXIN\"}";
cJSON* raw = cJSON_CreateRaw(rawJSON);
ShowValue(raw);//实际上将JSON原始串作为JSON的字段,本质还是一个cJSON Object
cJSON_Delete(raw);
raw = NULL;
//6.cJSON中NULl类型的创建和使用
cJSON*nullItem = cJSON_CreateNull();
ShowValue(nullItem);
cJSON_Delete(nullItem);
nullItem = NULL;
//7.cJSON中数组类型的创建和使用
///cJSON中的数组类型就有Int类型的数组,Float类型的数组,Double类型的数组,以及String类型的数组还有一个空的不含任何类型的数据的数组
///7.1 创建Int类型的数组
int intArray[5] = { 11,22,33,44,55 };
cJSON* intArrayItem = cJSON_CreateIntArray(intArray, 5);
ShowValue(intArrayItem);
cJSON_Delete(intArrayItem);
intArrayItem = NULL;
///7.2 创建Float类型的数组
float floatArray[4] = { 1.23f,2.67f,4.32f,8.912f };
cJSON*floatArrayItem = cJSON_CreateFloatArray(floatArray, 4);
ShowValue(floatArrayItem);
cJSON_Delete(floatArrayItem);
floatArrayItem = NULL;
///7.3 创建string类型的数组
const char* strArray[3] = { "Apple","Pair","Birth" };
cJSON*strArrayItem = cJSON_CreateStringArray(strArray, 3);
ShowValue(strArrayItem);
cJSON_Delete(strArrayItem);
strArrayItem = NULL;
///7.4 空数组类型
cJSON* emptyArrayItem = cJSON_CreateArray();
ShowValue(emptyArrayItem);
cJSON_Delete(emptyArrayItem);
emptyArrayItem = NULL;
//8.cJSON中的引用类型(这段内容极其重要,一定要深刻理解!!!)
///C++中封装带有指针类型的成员的时候,那么我们深知必须手动重载operator=和拷贝构造器,因为这很好理解,成员中的指针的空间是没有在堆上进行分配的(单纯的从另一个对象的有效指针拷贝过去,这会导致两次释放同一个内存空间的地址,也就是浅拷贝,那么我们重载的意义就是为深拷贝)
///对于cJSON中的引用类型也是一样的,刚刚那些创建的各种各样数据类型的cJSON_CreateXXX函数,都会从输入的数据中拷贝一份独立的走。而不会影响到我们的输入数据。
///那么这里面的引用类型就不一样了,在创建的时候,cJSON的创建器不会单独为cJSON节点中存储数据域的指针单独分配堆空间,再把输入数据拷贝进去。而是直接将输入的数据的地址直接和cJSON的节点进行关联(那么这就会引出一个问题,我们输入的内容若是动态分配的,那么使用引用传入cJSON节点,那么就需要自己管理释放的过程。因为cJSON节点即使是调用cJSON_Delete也不会帮我们释放我们那个输入的数据区的指针的内存空间,它只会释放cJSON结点本身的内存)
///通过一个案例来理解它
///这里创建一个String类型的cJSON节点,但是使用cJSON的引用创建方式去创建它
const char* string = "Hello,World!";
cJSON*stringRefItem = cJSON_CreateStringReference(string);
cout << "string address:" << (void*)string << endl;
cout << "stringRefItem address:" << (void*)stringRefItem->valuestring << endl;
///我们会发现,上面两个的地址是一模一样的,这印证了刚刚的猜想(需要注意的是,假设string是new出来的堆内存,那么即使是执行了cJSON_Delete了Item结点,string本身也没有从内存中释放,需要手动调用delete[]进行释放)
cJSON_Delete(stringRefItem);
stringRefItem = NULL;
//9.为什么cJSON设计的时候要设计引用类型和值拷贝的机制?
///很明显是为了性能开销的角度进行设计的,假设JSON串很大,反复的调用非引用传入的创建结点的函数,这会造成极大的性能开销,拖慢性能;但是引入了引用之后,起码也可以将内存占用减少一般,这对性能的影响可不小哦
return 0;
}
小结:
这一结我们一起学习了cJSON中的一些基本的数据类型,并已经熟悉了如何使用其内部的cJSON_CreateXXX函数来创建这些数据类型具体的cJSON的Item对象。另外我们还学习到了cJSON按照拷贝模式创建数据的结点和使用cJSON使用引用模式去创建cJSON结点的具体区别以及在内存管理上的一些细节和注意事项。在了解完了cJSON的基础数据类型之后。后续学习cJSON的操作这些数据Item对象的函数时,会更加容易且更容易理解这些内容。
浙公网安备 33010602011771号