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. */ }