解析JSON数据的主函数是cJSON_Parse,这个函数默认调用不带选项的cJSON_ParseWithOpts函数。
skip函数的作用是跳过字符串中的控制字符(和空白字符)
cJSON_ParseWithOpts函数首先创建一个JSON节点,然后跳过空白字符,接着调用parse_value函数进行数据的解析,然后判断解析是否出错,如果出错,那么释放内存,然后返回空指针,全局变量ep(char*类型)记录了出错的位置。如果没有出错,那么返回树形结构的JSON节点。
/* Parse an object - create a new root, and populate. */
// 带选项解析json数据
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
{
// 是否到达末尾
const char *end=0;
// 创建一个新的json节点
cJSON *c=cJSON_New_Item();
// ep是一个全局的静态变量(这个参数的作用目前还不知道:好象是记录解析达到的最终位置)
ep=0;
// 分配内存失败,返回
if (!c)
return 0; /* memory fail */
// 开始解析
// parse_value是进行解析的主要函数
// 它里面会根据节点的不同类型调用不同的解析函数
// 如果遇到数组或者对象,可能还会进行递归调用
end=parse_value(c,skip(value));
// end==0,出错,返回0
if (!end)
{
// 删除节点(以及它的子节点)
cJSON_Delete(c);
return 0;
} /* parse failure. ep is set. */
/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
// 判断是否需要以null结束
if (require_null_terminated)
{
// 跳过空白字符
end=skip(end);
// 如果最后end还有字符,表示格式错误等,返回0
if (*end)
{
cJSON_Delete(c);
ep=end;
return 0;
}
}
// 判断是否需要返回解析的尾部
if (return_parse_end)
*return_parse_end=end;
// 返回json节点
return c;
}
skip函数的作用是跳过字符串中的控制字符(和空白字符)
/* Utility to jump whitespace and cr/lf */
// 跳过一切的空白字符
static const char *skip(const char *in)
{
while (in && *in && (unsigned char)*in<=32)
in++;
return in;
}
parse_value函数事实上进行数据解析的函数,会根据不同字符串内容的不同,调用不同的解析函数(例如parse_object等函数,parse_object这些函数内部可能又会递归调用parse_value进行解析)进行具体的解析
/* Parser core - when encountering text, process appropriately. */
// 解析json格式的主要函数,解析值
static const char *parse_value(cJSON *item,const char *value)
{
if (!value)
return 0; /* Fail on null. */
// 如果这个值是null,表明是null节点
if (!strncmp(value,"null",4))
{
item->type=cJSON_NULL;
return value+4;
}
// 如果这个值是false,那么表示这是一个布尔节点
if (!strncmp(value,"false",5))
{
item->type=cJSON_False;
return value+5;
}
// 如果这个值是true,表示这个节点是布尔节点
if (!strncmp(value,"true",4))
{
item->type=cJSON_True;
item->valueint=1;
return value+4;
}
// 如果是双引号开头,那么表示这个是一个字符串
if (*value=='\"')
{
// 开始解析字符串
return parse_string(item,value);
}
// 如果以负号开头或者以数字开头,那么表示这是一个数值
if (*value=='-' || (*value>='0' && *value<='9'))
{
// 开始解析数值
return parse_number(item,value);
}
// 如果以左中括号开头,那么表示是一个数组
if (*value=='[')
{
// 开始解析数组
return parse_array(item,value);
}
// 如果以左大括号开头,那么表示是一个对象
if (*value=='{')
{
return parse_object(item,value);
}
// 记录解析的位置
ep=value;
// 到达这里表示解析出错
return 0; /* failure. */
}