Nuestros mejores desarrolladores han agotado sus depósitos de café, por su búsqueda día y noche por la respuesta, hasta que Fabián halló el hallazgo en Gitea y ahora la compartimos contigo.
Solución:
El documento menciona sobre parse_object().
Creo que esto es lo que tienes que hacer.
void parse_object(cJSON *root)
cJSON* name = NULL;
cJSON* index = NULL;
cJSON* optional = NULL;
int i;
cJSON *item = cJSON_GetObjectItem(items,"items");
for (i = 0 ; i < cJSON_GetArraySize(item) ; i++)
cJSON * subitem = cJSON_GetArrayItem(item, i);
name = cJSON_GetObjectItem(subitem, "name");
index = cJSON_GetObjectItem(subitem, "index");
optional = cJSON_GetObjectItem(subitem, "optional");
Llame a esta función como
request_json = cJSON_Parse(request_body);
parse_object(request_json);
Si quieres correr un poco más rápido, así es como se ve el código:
void parse_array(cJSON *array)
cJSON *item = array ? array->child : 0;
while (item)
cJSON *name = cJSON_GetObjectItem(item, "name");
cJSON *index = cJSON_GetObjectItem(item, "index");
cJSON *optional = cJSON_GetObjectItem(item, "optional");
item=item->next;
Esto evita el costo O(n^2) que RBerteig señala correctamente.
Llamar con:
parse_array(cJSON_GetObjectItem(cJSON_Parse(request_body),"items"));
En mi humilde opinión, este es un ejemplo de un caso en el que debe romper la encapsulación de la biblioteca y trabajar directamente con su estructura de datos de objetos. cJSON.h
define el objeto central como el siguiente struct
:
/* The cJSON structure: */
typedef struct cJSON
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
int type; /* The type of the item, as above. */
char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
cJSON;
(Uno podría cuestionar algunas de las elecciones de nombres que hizo el autor, por supuesto. Pero un buen nombre es duro.)
los key Lo que hay que tener en cuenta es que tanto los objetos JSON como las matrices JSON tienen unnull child
campo, que apunta a una lista doblemente enlazada de sus hijos. Los hijos de JSON Objects también tienennull string
campos que contiene el nombre de campo asociado con ese hijo.
Entonces, para iterar genéricamente sobre la matriz JSON ja
en tiempo O(n), llamando a una función para cada elemento, escribes algo como esto:
cJSON_ForEachItem(cJSON *ja, int (*f)(cJSON *ja, int i, cJSON *jchild))
cJSON *jchild;
int i;
for (jchild=ja->child, i=0; jchild; jchild=jchild->next, ++i)
// do something here with the ith child...
if (f(ja, i, jchild))
break;
Dado que los objetos y las matrices solo difieren internamente en la presencia de nombres para cada elemento secundario, esa función también iterará los campos de un objeto. La devolución de llamada puede decir porque ja->type
será cualquiera cJSON_Array
o cJSON_Object
y jchild->string
será no-null para Objetos también.
Haciendo la misma iteración llamando cJSON_GetArraySize()
y usando cJSON_GetArrayItem()
será de orden O (n ^ 2) porque tiene que atravesar la lista vinculada cada vez para ubicar el enésimo elemento.
Podría decirse que cJSON debería incluir algunos genéricos ForEach
funciones, pero eso podría representar el comienzo de una cantidad significativa de alcance que se aleja de su objetivo original declarado de ser "el analizador más tonto posible con el que puede hacer su trabajo".
Valoraciones y comentarios
Tienes la posibilidad dar recomendación a esta reseña si te fue útil.