话不多说,上代码(示例)。
.... //以下代码示例组装一个json数组结点destarray cJSON *destarray = nullptr; destarray = cJSON_CreateArray(); //创建一个空的json目标数组结点 cJSON *dbarray = nullptr; dbarray = DBgetxxx(); //从其它地方获取的json数组,比如通过 sqlite 库中db_query_sql_json_new接口从数据库获取的 if (dbarray != nullptr) { int size = cJSON_GetArraySize(dbarray); for (int i = 0; i < size; i++) { cJSON * arrayItem = cJSON_GetArrayItem(dbarray, i); //从dbarray取出子json if (arrayItem != nullptr) { cJSON_AddItemToArray(destarray, arrayItem); //将子json添加到目标array中 } } .... } ....//继续添加其它json数据到destarray结点
嗯看着似乎没啥问题,但是实际调试的时候却发现,只有dbarray中的第一个子json成功地添加到了destarray中,后面的子json都没添加成功,如果添加调试就会发现,这些没添加成功的arrayItem 是nullptr
检查一下cJSON中cJSON_GetArrayItem 和 cJSON_AddItemToArray的源码:
static cJSON* get_array_item(const cJSON *array, size_t index) { cJSON *current_child = NULL; if (array == NULL) { return NULL; } current_child = array->child; while ((current_child != NULL) && (index > 0)) { index--; current_child = current_child->next; } return current_child; } static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) { cJSON *child = NULL; if ((item == NULL) || (array == NULL) || (array == item)) { return false; } child = array->child; if (child == NULL) { array->child = item; item->prev = item; item->next = NULL; } else { if (child->prev) { suffix_object(child->prev, item); array->child->prev = item; } } return true; }
问题就出在add_item_to_array中当array->child == NULL的时候,会将item->next置为NULL,说白了就是在本例中,当目标json数组destarray是空的时候,第一次调用cJSON_AddItemToArray(destarray,arrayItem);的时候,会将arrayItem的next指针置为空。而arrayItem是dbarray的一个child,arrayItem->next就是dbarray的下一个child,这可不就导致出问题了。
知道了原因那就好办了,解决方法示例:
... if (dbarray != nullptr) { int size = cJSON_GetArraySize(dbarray); cJSON *arrayItem [size] = {0}; for (int i = 0; i < size; i++) { cJSON * arrayItem[i] = cJSON_GetArrayItem(dbarray, i); //从dbarray取出子json,先用数组存起来,存完再统一添加到destarray } for (int j = 0; j < size; j++) { if (arrayItem[j] != nullptr) { cJSON_AddItemToArray(destarray,arrayItem[j]); } } } ....
总之,使用cJSON_AddItemToArray的时候小心一点就是了~