首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用cJSON读入JSON数组

使用cJSON读入JSON数组
EN

Stack Overflow用户
提问于 2013-06-03 23:55:19
回答 4查看 45K关注 0票数 13

我正在尝试使用由Dave Gamble编写的cJSON库来读取以下JSON数组:

代码语言:javascript
复制
"items": 
[
    {
        "name": "command",
        "index": "X",
        "optional": "0"
    },
    {
        "name": "status",
        "index": "X",
        "optional": "0"
    }
]

通过阅读他的documentation,我找到了读入单个对象的方法,但没有关于数组的内容,而且我无法从给出的示例中猜测如何做到这一点。

这是我正在尝试的:

代码语言:javascript
复制
cJSON* request_json = NULL;
cJSON* items = cJSON_CreateArray();
cJSON* name = NULL;
cJSON* index = NULL;
cJSON* optional = NULL;

request_json = cJSON_Parse(request_body);

items = cJSON_GetObjectItem(request_json, "items");

name = cJSON_GetObjectItem(items, "name");
index = cJSON_GetObjectItem(items, "index");
optional = cJSON_GetObjectItem(items, "optional");

我知道这是错误的,不仅仅是因为它不工作,而且我不知道如何让它正确。

显然,我需要循环读入数组中每个索引的所有条目。我不知道该如何做,因为我不知道在这段代码中应该在哪里使用索引,也不知道这是不是一个正确的开始。有一个cJSON_GetArrayItem(),但它只需要一个数字(假设是一个索引),不需要字符串来指示它想要哪个字段。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-06-04 00:20:51

文档中提到了parse_object()。

我认为这就是你需要做的。

代码语言:javascript
复制
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"); 
  }
}

将此函数调用为

代码语言:javascript
复制
request_json = cJSON_Parse(request_body);
parse_object(request_json);
票数 22
EN

Stack Overflow用户

发布于 2016-05-28 08:49:00

如果你想运行得稍微快一点,代码看起来是这样的:

代码语言:javascript
复制
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;
  }
}

这避免了RBerteig正确指出的O(n^2)开销。

通过以下方式进行呼叫:

代码语言:javascript
复制
parse_array(cJSON_GetObjectItem(cJSON_Parse(request_body),"items"));
票数 5
EN

Stack Overflow用户

发布于 2014-08-07 06:42:18

我的意思是,这是一个例子,你应该拆分库的封装,并直接使用它的对象数据结构。cJSON.h将核心对象定义为以下struct

代码语言:javascript
复制
/* 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;

(当然,人们可以对作者做出的一些命名选择吹毛求疵。但是好的命名是很难的。)

需要注意的关键是,JSON对象和JSON数组都有一个非空的child字段,该字段指向其子对象的双向链表。JSON对象的子对象也有非空的string字段,其中包含与该子对象关联的字段名。

因此,要在O(n)时间内迭代JSON数组ja,为每个元素调用一个函数,您可以编写如下代码:

代码语言:javascript
复制
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;
    }
}

由于对象和数组在内部的不同之处在于每个子项的名称,因此该函数还将迭代对象的字段。回调可以判断,因为ja->type将是cJSON_ArraycJSON_Object,并且对象的jchild->string也将是非空的。

通过调用cJSON_GetArraySize()并使用cJSON_GetArrayItem()进行相同的迭代将是O(n^2),因为它每次都必须遍历链表以定位第n项。

可以说,cJSON应该包含一些通用的ForEach函数,但这可能代表着大量作用域的开始-它宣称的原始目标是“可以完成工作的最愚蠢的解析器”。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16900874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档