解析cJSON:如何准确读取和判断数据类型**
在C语言中处理JSON数据,cJSON无疑是一个非常流行且轻量级的库,它将JSON数据解析成C语言中的数据结构,使得开发者可以方便地操作这些数据,正确地读取和判断JSON中元素的数据类型,是使用cJSON进行数据解析的关键步骤,本文将详细介绍如何使用cJSON提供的API来准确读取和判断数据类型。
cJSON的核心数据结构与类型概念
我们需要了解cJSON的基本组织方式和数据类型表示。
- cJSON结构体:cJSON库的核心是一个
cJSON结构体,每个JSON对象(Object)、数组(Array)、字符串(String)、数字(Number)等都对应一个cJSON结构体实例。 - 数据类型枚举:
cJSON结构体中有一个重要的成员type,它是一个枚举类型cJSON_Type,定义了所有可能的数据类型:typedef enum { cJSON_Invalid = -1, // 无效类型 cJSON_False = 0, // 布尔值 false cJSON_True = 1, // 布尔值 true cJSON_NULL = 2, // null 值 cJSON_Number = 3, // 数字 (整数或浮点数) cJSON_String = 4, // 字符串 cJSON_Array = 5, // 数组 cJSON_Object = 6, // 对象 cJSON_Raw = 7 // 原始JSON字符串 (不常用,通常用于特殊优化) } cJSON_Type;
判断数据类型的主要方法
cJSON提供了多种方法来判断和获取数据类型,最常用的是通过检查type成员以及使用专门的查询函数。
直接检查 type 成员
这是最底层也是最直接的方法,通过访问cJSON结构体的type成员,我们可以精确地知道它所代表的JSON数据类型。
#include <stdio.h>
#include <cJSON.h>
void check_type_by_direct(const cJSON *item) {
if (item == NULL) {
printf("Item is NULL\n");
return;
}
switch (item->type) {
case cJSON_False:
printf("Type: Boolean (false)\n");
break;
case cJSON_True:
printf("Type: Boolean (true)\n");
break;
case cJSON_NULL:
printf("Type: NULL\n");
break;
case cJSON_Number:
printf("Type: Number\n");
// 进一步判断是整数还是浮点数(见下文)
break;
case cJSON_String:
printf("Type: String\n");
break;
case cJSON_Array:
printf("Type: Array\n");
break;
case cJSON_Object:
printf("Type: Object\n");
break;
case cJSON_Raw:
printf("Type: Raw\n");
break;
default:
printf("Type: Unknown\n");
break;
}
}
使用便捷的查询函数
为了简化操作,cJSON提供了一系列以cJSON_Is开头的宏或函数,它们内部会检查type成员并返回布尔值,使代码更具可读性。
cJSON_IsInvalid(item):检查是否为无效类型。cJSON_IsFalse(item):检查是否为布尔值false。cJSON_IsTrue(item):检查是否为布尔值true。cJSON_IsNull(item):检查是否为NULL。cJSON_IsBool(item):检查是否为布尔值(true或false)。cJSON_IsNumber(item):检查是否为数字。cJSON_IsString(item):检查是否为字符串。cJSON_IsArray(item):检查是否为数组。cJSON_IsObject(item):检查是否为对象。cJSON_IsRaw(item):检查是否为原始JSON字符串。
示例:
#include <stdio.h>
#include <cJSON.h>
void check_type_by_convenience(const cJSON *item) {
if (item == NULL) {
printf("Item is NULL\n");
return;
}
if (cJSON_IsNumber(item)) {
printf("Type: Number\n");
} else if (cJSON_IsString(item)) {
printf("Type: String\n");
} else if (cJSON_IsBool(item)) {
printf("Type: Boolean (%s)\n", cJSON_IsTrue(item) ? "true" : "false");
} else if (cJSON_IsNull(item)) {
printf("Type: NULL\n");
} else if (cJSON_IsArray(item)) {
printf("Type: Array\n");
} else if (cJSON_IsObject(item)) {
printf("Type: Object\n");
} else {
printf("Type: Unknown or Invalid\n");
}
}
获取数据类型对应的具体值
判断了数据类型后,我们需要获取其对应的值,cJSON为每种类型提供了相应的获取函数。
布尔值 (Boolean)
cJSON_IsTrue(item):如果item为布尔值true,返回非零;否则返回0。cJSON_IsFalse(item):如果item为布尔值false,返回非零;否则返回0。- 注意:cJSON中布尔值是用
cJSON_True(值为1) 和cJSON_False(值为0) 这两个常量表示的,可以直接比较。
数字 (Number)
cJSON的数字类型可能是整数也可能是浮点数,它内部使用double类型来存储所有数字。
cJSON_GetNumberValue(item):获取数字值,返回double类型。- 如果JSON中是整数,返回的
double值可以安全地转换为整数(如果数值范围在int或long范围内)。 - 如果JSON中是浮点数,返回的就是浮点数。
- 如果JSON中是整数,返回的
如何区分整数还是浮点数?
cJSON本身不直接区分数字是整数还是浮点数,它只存储为double,你需要根据数字的值或者JSON原始字符串的格式来判断,如果cJSON_GetNumberValue(item)返回的值的小数部分为0,并且数值在整数范围内,那么可以认为它是一个整数。
cJSON *number_item = cJSON_GetObjectItemCaseSensitive(root, "age");
if (cJSON_IsNumber(number_item)) {
double num_val = cJSON_GetNumberValue(number_item);
printf("Number value: %f\n", num_val);
// 假设我们知道age应该是整数
int age = (int)num_val; // 注意:这里可能有精度丢失风险,如果num_val很大
printf("Age (as int): %d\n", age);
}
字符串 (String)
cJSON_GetStringValue(item):获取字符串值,返回const char*指针,如果item不是字符串类型或为NULL,返回NULL。cJSON_IsString(item):先判断是否为字符串类型。
cJSON *name_item = cJSON_GetObjectItemCaseSensitive(root, "name");
if (cJSON_IsString(name_item)) {
const char *name = cJSON_GetStringValue(name_item);
printf("Name: %s\n", name ? name : "(null)");
}
NULL值
cJSON_IsNull(item):检查是否为NULL值,没有获取函数,因为NULL值本身没有内容。
数组 (Array) 和对象 (Object)
对于数组(Array)和对象(Object),我们通常不直接获取一个“值”,而是遍历其元素或成员。
-
数组遍历:
cJSON_GetArraySize(array_item):获取数组元素个数。cJSON_GetArrayItem(array_item, index):获取指定索引的元素(cJSON*类型)。cJSON_ArrayForEach(iterable_element, array_item):宏,用于遍历数组中的每个元素。
-
对象遍历:
cJSON_GetObjectItemCaseSensitive(object_item, key):根据键(区分大小写)获取对应的值(cJSON*类型)。cJSON_GetObjectItem(object_item, key):根据键(不区分大小写)获取对应的值(cJSON*类型)。cJSON_GetArraySize(object_item):获取对象的成员个数(因为对象内部实现也是数组)。cJSON_GetArrayItem(object_item, index):获取对象中第index个成员(键值对中的值部分)。cJSON_ObjectForEach(iterable_element, object_item):宏,用于遍历对象中的每个成员(iterable_element是当前成员的cJSON*,



还没有评论,来说两句吧...