cJSON开源项目详细解剖3

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: cJSON开源项目详细解剖3

cJSON_DetachItemFromArray

/*
功 能:将元素从数组中分离
参 数:array-数组  which-下标(要分离元素的下标)
返回值:分离后元素的地址
*/
cJSON* cJSON_DetachItemFromArray(cJSON* array, int which)
{
  cJSON* c = array->child;    // 指向第一个儿子(第0个元素)
  while (NULL != c && which > 0)  // 寻找要分离的元素位置
  {
    c = c->next;
    which--;
  }
  if (NULL == c)          // 指针为NULL
  {
    return NULL;
  }
  if (NULL != c->prev)      // 要分离的元素不是第0个元素
  {
    c->prev->next = c->next;
  }
  if (NULL != c->next)      // 要分离的元素不是最后一个元素
  {
    c->next->prev = c->prev;
  }
  if (c == array->child)      // 要分离的元素是第0个元素
  {
    array->child = c->next;
  }
  c->prev = c->next = NULL;   // 其他情况
  return c;
}

cJSON_DeleteItemFromArray

/* 从数组中删除元素 */
void   cJSON_DeleteItemFromArray(cJSON* array, int which)
{
  cJSON_Delete(cJSON_DetachItemFromArray(array, which));
}


cJSON_DetachItemFromObject

/*
功 能:从对象中分离元素
参 数:object-对象  string-要查找元素的key
返回值:元素分离后的地址
*/
cJSON* cJSON_DetachItemFromObject(cJSON* object, const char* string)
{
  int i = 0;
  cJSON* c = object->child;
  while (NULL != c && 0 != cJSON_strcasecmp(c->string, string)) // 查找要删除的key为string
  {
    i++;
    c = c->next;
  }
  if (NULL != c)                          // 找到了
    return cJSON_DetachItemFromArray(object, i);
  return NULL;
}

cJSON_DeleteItemFromObject

/* 从对象中删除元素 */
void   cJSON_DeleteItemFromObject(cJSON* object, const char* string)
{
  cJSON_Delete(cJSON_DetachItemFromObject(object, string));
}

JSON_InsertItemInArray

/*
功 能:添加元素到数组或者对象中
参 数:array-数组  which-插入的下标(从0开始)  newitem-插入的新元素(新节点)
返回值:无
*/
void JSON_InsertItemInArray(cJSON* array, int which, cJSON* newitem)
{
  cJSON* c = array->child;          // 用于保存插入的元素节点
  while (NULL != c && which > 0)        // 找插入的位置
  {
    c = c->next;
    which--;
  }
  if (NULL == c)                // 发现插入位置大于等于数组元素个数
  {
    cJSON_AddItemToArray(array, newitem); // 添加到数组最后
    return;
  }
  /* 连接新节点 */
  newitem->next = c;              
  newitem->prev = c->prev;
  c->prev = newitem;
  if (c == array->child)            // 如果是第0个元素(第一个儿子)
    array->child = newitem;
  else
    newitem->prev->next = newitem;
}


cJSON_ReplaceItemInArray

/*
作 用:将newiem节点替换为array的第which子节点
参 数:array-根节点, which-替换的第几个子节点  newitem-新的子节点
返回值:无
*/
void cJSON_ReplaceItemInArray(cJSON* array, int which, cJSON* newitem)
{
  cJSON* c = array->child;
  while (NULL != c && which > 0)      // 找到需要替换的子节点
  {
    c = c->next;
    which--;
  }
  if (NULL == c)              // 替换的位置超过目前节点
  {
    return;
  }
  newitem->next = c->next;        // 新节点连接弟弟节点
  newitem->prev = c->prev;        // 新节点连接哥哥节点
  if (NULL != newitem->next)        // 新节点不是最后一个    
  {
    newitem->next->prev = newitem;    // 弟弟节点连接新节点
  }
  if (c == array->child)          // 若被替换的节点是父节点的第一个孩子节点
  {
    array->child = newitem;       // 就将父节点的孩子节点设置为新节点
  }
  else
  {
    newitem->prev->next = newitem;    // 哥哥节点连接新节点
  }
  c->next = NULL;             // 将旧节点指针置为空
  c->prev = NULL;             // 将旧节点指针置为空
  cJSON_Delete(c);            // 回收被替换的指针内存
}


cJSON_ReplaceItemInObject

/*
作 用:用新的value,替换object对象中key==string那一个子节点
参 数:object-被替换的根对象的一个子节点    string-被替换的key    newitem-新子节点的value
返回值:无
*/
void cJSON_ReplaceItemInObject(cJSON* object, const char* string, cJSON* newitem)
{
  int i = 0;
  cJSON* c = object->child;
  while (NULL != c && cJSON_strcasecmp(c->string, string))// 查找object下key为string的子节点
  {
    i++;
    c = c->next;
  }
  if (NULL != c)                      // 找到了
  {
    newitem->string = cJSON_strdup(string);       // 在堆区存放字符串的地址给到子节点的key
    cJSON_ReplaceItemInArray(object, i, newitem);   // 将object的第i个子节点替换为newitem
  }
}

cJSON_CreateNull

/* 创建子结构体(类型为NULL) */
cJSON* cJSON_CreateNull(void)
{
  cJSON* item = cJSON_New_Item();         // 向堆区给结构体申请一块空间
  if (NULL == item)               // 申请空间成功
  {
    return NULL;
  }
  item->type = cJSON_NULL;            // 将结构体的type类型设置为true
  return item;                  // 返回结构体地址
}


cJSON_CreateTrue

/* 创建子结构体(类型为true) */
cJSON* cJSON_CreateTrue(void)
{
  cJSON* item = cJSON_New_Item();         // 向堆区给结构体申请一块空间
  if (NULL == item)               // 申请空间成功
  {
    return NULL;
  }
  item->type = cJSON_True;            // 将结构体的type类型设置为true
  return item;                  // 返回结构体地址
}


cJSON_CreateFalse

/* 创建子结构体(类型为false) */
cJSON* cJSON_CreateFalse(void)
{
  cJSON* item = cJSON_New_Item();         // 向堆区给结构体申请一块空间
  if (NULL == item)               // 申请空间失败
  {
    return NULL;
  }
  item->type = cJSON_False;           // 将结构体的type类型设置为false
  return item;                  // 返回结构体地址
}


cJSON_CreateBool

/* 创建子结构体(类型为bool) */
cJSON* cJSON_CreateBool(int b)
{
  cJSON* item = cJSON_New_Item();         // 向堆区给结构体申请一块空间
  if (NULL == item)               // 申请空间失败
  { 
    return NULL;
  }
  item->type = b ? cJSON_True : cJSON_False;    // 设置结构体的type类型为bool
  return item;            
}


cJSON_CreateNumber

/* 创建子结构体(类型为数字) */
cJSON* cJSON_CreateNumber(double num)
{
  cJSON* item = cJSON_New_Item();         // 向堆区给结构体申请一块空间
  if (NULL == item)               // 申请空间失败
  {
    return NULL;
  }
  item->type = cJSON_Number;            // 将结构体的type类型设置为数字
  item->valuedouble = num;            // 将num给到valuedouble
  item->valueint = (int)num;            // 将num给到valueint
  return item;                  
}


cJSON_CreateString

/* 创建子结构体(类型为字符串) */
cJSON* cJSON_CreateString(const char* string)   // 参数const防止字符串被修改
{
  cJSON* item = cJSON_New_Item();         // 向堆区给结构体申请一块空间
  if (NULL == item)               // 申请空间失败
  {
    return NULL;
  }
  item->type = cJSON_String;            // 将结构体的type类型设置为字符串
  item->valuestring = cJSON_strdup(string);   // 将堆区开辟的空间地址给到valuestring中
  return item;                
}


cJSON_CreateArray

/* 创建子结构体(类型为数组)  */
cJSON* cJSON_CreateArray(void)
{
  cJSON* item = cJSON_New_Item();         // 向堆区给结构体申请一块空间
  if (NULL == item)               // 申请空间失败
  {
    return NULL;
  }
  item->type = cJSON_Array;           // 将结构体的type类型设置为字符串
  return item;
}


cJSON_CreateObject

/* 创建子结构体(类型为对象)  */
cJSON* cJSON_CreateObject(void)
{
  cJSON* item = cJSON_New_Item();         // 向堆区给结构体申请一块空间
  if (NULL == item)               // 申请空间失败
  {
    return NULL;
  }
  item->type = cJSON_Object;            // 将结构体的type类型设置为字符串
  return item;
}


cJSON_CreateIntArray

/*
功 能:创建一个数组结构体
参 数:number-数组指针 count-数组的长度
返回值:返回数组结构体地址
*/
cJSON* cJSON_CreateIntArray(const int* numbers, int count)
{
  int i = 0;                
  cJSON* n = 0;             // 保存创建的子结构体(子节点)地址
  cJSON* p = 0;             // 保存每次更新后的前一个节点(父节点或者哥哥节点)
  cJSON* a = cJSON_CreateArray();     // 保存创建的父结构体(父节点)地址
  if (NULL == a)              // 堆区内存申请失败
    return NULL;
  for (i = 0; i < count; i++)
  {
    n = cJSON_CreateNumber(numbers[i]); // 创建子结构体(类型为数字)
    if (NULL == n)            // 堆区内存申请失败
      return NULL;
    if (0 == i)             // 第一个子节点,就是父节点的儿子(child)
      a->child = n;
    else                
      suffix_object(p, n);      // 将兄弟节点连接起来
    p = n;                // 更新前一个节点
  }
  return a;               // 返回父节点的地址
}

cJSON_CreateFloatArray

/*
功 能:创建浮点型数组
参 数:numbers-双精度数组指针 count-数组个数
返回值:返回数组结构体指针
*/
cJSON* cJSON_CreateFloatArray(const float* numbers, int count)
{
  int i = 0;
  cJSON* n = 0;             // 接收数字类型结构体的地址
  cJSON* p = 0;             // 保存每次更新后的前一个节点(父节点或者哥哥节点)
  cJSON* a = cJSON_CreateArray();     // 保存创建的父结构体(父节点)地址
  if (NULL == a)              // 堆区内存申请失败
    return NULL;
  for (i = 0; NULL != a && i < count; i++)
  {
    n = cJSON_CreateNumber(numbers[i]); // 创建子结构体(类型为数字)
    if (NULL == n)            // 堆区内存申请失败
      return NULL;
    if (0 == i)             // 第一个儿子
      a->child = n;
    else
      suffix_object(p, n);      // 连接兄弟节点
    p = n;                // 更新前一个节点
  }
  return a;
}

cJSON_CreateDoubleArray

/*
功 能:创建双进度型数组或者对象的结构体
参 数:numbers-双精度数组指针 count-数组个数
返回值:返回数组结构体指针
*/
cJSON* cJSON_CreateDoubleArray(const double* numbers, int count)
{
  int i = 0;
  cJSON* n = 0;               // 接收数字类型结构体的地址
  cJSON* p = 0;               // 保存每次更新后的前一个节点(父节点或者哥哥节点)
  cJSON* a = cJSON_CreateArray();       // 保存创建的父结构体(父节点)地址
  if (NULL == a)                // 堆区内存申请失败
    return NULL;
  for (i = 0; NULL != a && i < count; i++)
  {
    n = cJSON_CreateNumber(numbers[i]);   // 创建子结构体(类型为数字)
    if (NULL == n)              // 堆区内存申请失败
      return NULL;
    if (0 == i)               // 第一个儿子
      a->child = n;
    else
      suffix_object(p, n);        // 连接兄弟节点
    p = n;
  }
  return a;
}

cJSON_CreateStringArray

/*
功 能:创建字符串数组或者对象
参 数:strings-字符串数组指针 count-数组个数
返回值:返回数组结构体指针
*/
cJSON* cJSON_CreateStringArray(const char** strings, int count)
{
  int i = 0;
  cJSON* n = 0;               // 接收字符串类型结构体的地址
  cJSON* p = 0;               // 保存每次更新后的前一个节点(父节点或者哥哥节点)
  cJSON* a = cJSON_CreateArray();       // 保存创建的父结构体(父节点)地址
  if (NULL == a)                // 堆区内存申请失败
    return NULL;
  for (i = 0; NULL != a && i < count; i++)
  {
    n = cJSON_CreateString(strings[i]);   // 创建子结构体(类型为字符串)
    if (NULL == n)              // 堆区内存申请失败
      return NULL;
    if (0 == i)               // 第一个儿子
      a->child = n;
    else
      suffix_object(p, n);        // 连接兄弟节点
    p = n;
  }
  return a;
}

cJSON_Duplicate

/*
功 能:深复制一份结构体
参 数:item-结构体指针  recurse-递归层数
返回值:返回新复制的地址
*/
cJSON* cJSON_Duplicate(cJSON* item, int recurse)
{
  cJSON* newitem = NULL;    // 保存首地址
  cJSON* cptr = NULL;     // 拷贝区域的指针
  cJSON* nptr = NULL;     // 原区域的指针
  cJSON* newchild = NULL;   // 新子节点
  if (NULL == item)
    return NULL;
  newitem = cJSON_New_Item();
  if (NULL == newitem)
    return NULL;
  /* 复制所有的变量 */
  newitem->type = item->type;
  newitem->valueint = item->valueint;
  newitem->valuedouble = item->valuedouble;
  if (NULL != item->valuestring)                  // 拷贝value
  {
    newitem->valuestring = cJSON_strdup(item->valuestring);
    if (NULL == newitem->valuestring)             // 开辟失败
    {
      cJSON_Delete(newitem);
      return NULL;
    }
  }
  if (NULL != item->string)                   // 拷贝key
  {
    newitem->string = cJSON_strdup(item->string);
    if (NULL == newitem->string)                // 开辟失败
    {
      cJSON_Delete(newitem);
      return 0;
    }
  }
  /* 如果是非递归的,那么我们就完成了! */
  if (0 == recurse)                 
    return newitem;
  /* 递归复制 */
  cptr = item->child;
  while (cptr)
  {
    newchild = cJSON_Duplicate(cptr, 1);
    if (NULL == newchild)               // 开辟失败
    {
      cJSON_Delete(newitem);
      return 0;
    }
    if (NULL != nptr)                 // 不是第一个儿子                  
    {
      nptr->next = newchild;              // 连接兄弟节点         
      newchild->prev = nptr;
      nptr = newchild;                // 更新拷贝区域的指针          
    }
    else                        // 第一个儿子
    {
      newitem->child = newchild;            // 设置为父节点的儿子
      nptr = newchild;                // 更新拷贝区域的指针
    }     
    cptr = cptr->next;                  // 更新原区域
  }
  return newitem;
}

cJSON_Minify

/*
功 能:移除文档中的所有空白和注释,实现对 JSON 内容的最小化压缩。实现无开销和近乎完美的表现 
参 数:json-结构体指针
返回值:无
*/
void cJSON_Minify(char* json)
{
  char* into = json;
  while ('\0' != *json)
  {
    if (*json == ' ')               // 是空格
      json++;
    else if (*json == '\t')             // 是制表符\t
      json++;
    else if (*json == '\r')             // \r回到当前行的行首,而不会换到下一行,如果接着输出的话,本行以前的内容会被逐一覆盖;
      json++;
    else if (*json == '\n')             // 换行符
      json++;
    else if (*json == '/' && json[1] == '/')    // C++风格注释
      while (*json && *json != '\n')        // 不是\0也不是换行符
        json++;
    else if (*json == '/' && json[1] == '*')    // c风格注释/*
    {
      while ('\0' != *json && !(*json == '*' && json[1] == '/'))  // 到*/注释结束
        json++;
      json += 2;                  // 最后跳过 */ 俩个字节
    }
    else if (*json == '\"')             // 字符串 开始
    {
      *into++ = *json++;              // 开始拷贝
      while ('\0' != *json && *json != '\"')    // 到 \" 结束
      {
        if (*json == '\\')            // 发现是转义字符,会多占一个字节
          *into++ = *json++;
        *into++ = *json++;
      }
      *into++ = *json++;
    }
    else 
      *into++ = *json++;              // 其他所有字符
  }
  *into = '\0';
}

printbuffer(输出缓冲区结构)

/* 输出缓冲区结构体 */
typedef struct printbuffer
{
  char* buffer;   // 缓冲区
  int length;     // 长度
  int offset;     // 偏移量
} printbuffer;

自定义内存管理函数

static void* (*cJSON_malloc)(size_t sz) = malloc;   // 将cJSON_malloc定义为malloc函数指针
static void (*cJSON_free)(void* ptr) = free;      // 将cJSON_free定义为free函数指针

测试文件

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
/*
作 用:将一个字符串文本解析为JSON格式,成功就返回文本在堆区的地址,失败就返回不能解析的地址然后打
      印不能解析的字符串部分回收堆区结构体内存。然后打印输出。再回收堆区存储解析好的文本
参 数:字符串地址
返回值:无
 */
void doit(char* text)
{
  char* out;          // 用于保存解析后的字符串地址
  cJSON* json;        // 用于保存构造的树结构体地址
  json = cJSON_Parse(text); // 使用json格式将字符串构造成一个树结构体,并保存在堆区,返回堆区地址
  if (json == NULL)
  {
    printf("Error before: [%s]\n", cJSON_GetErrorPtr());  // 打印不能被json解析的字符串
  }
  else
  {
    out = cJSON_Print(json);// 将树结构体使用json解析为字符串,并保存在堆区,返回堆区地址
    cJSON_Delete(json);   // 释放树结构体在堆区的空间
    printf("%s\n", out);  // 打印解析后的字符串
    free(out);        // 释放堆区解析好的字符串空间
  }
}
/* 从文件中读取字符串文本 */
void dofile(char* filename)
{
  FILE* f; // 文件指针
  long int len;
  char* data;
  f = fopen(filename, "rb");  // 以二进制方式读模式打开文件filename
  if (NULL == f)
  {
    printf("文件打开失败!\n");
    return;
  }
  fseek(f, 0, SEEK_END);    // 将文件指针定义到文件尾部,回退0个字节
  len = ftell(f);       // 返回文件指针与文件开始处的字节数,即文件总字节数
  fseek(f, 0, SEEK_SET);    // 将文件指针定义到文件开始处,向后0个字节
  data = (char*)calloc(len + 1, 1);   // 申请一块大于文件总字节数的空间,并初始化为0
  fread(data, 1, len, f);   // 将len个1大小字节的值拷贝到data内存中。返回成功读取的个数
  fclose(f);          // 关闭fp指定文件,必要时刷新缓冲区(关闭失败返回EOF,成功返回0)
  doit(data);         // 将字符串(data)先构造成树结构体,然后将书结构体使用json解析成字符串,并打印输出。
  free(data);         // 释放堆区解析好的字符串空间
}
/* 下面测试代码用到的结构体 */
struct record
{
  const char* precision;
  double lat, lon;
  const char* address, * city, * state, * zip, * country;
};
/* 创建一组对象作为演示 */
void create_objects(void)
{
  cJSON* root;        // 根节点(根结构体)
  cJSON* fmt;         // 用于保存视频实例中子对象的地址
  cJSON* img;         // 用于保存走廊实例中子对象的地址
  cJSON* thm;         // 用于保存走廊实例中子子对象的地址
  cJSON* fld;         // 用于保存唱片实例中子子对象的地址
  char* out;          // 保存解析后字符串在堆区的地址
  int i;            // 用于遍历
  /* 星期数(数组) */
  const char* strings[7] = { "Sunday","Monday","Tuesday","Wednesday",
    "Thursday","Friday","Saturday" };
  /* 矩阵(二维数组) */
  int numbers[3][3] = { {0,-1,0},{1,0,0},{0,0,1} };
  /* 走廊(数组) */
  int ids[4] = { 116,943,234,38793 };
  /* 唱片(结构体数组) */
  struct record fields[2] = 
  {
    {"zip",37.7668,-1.223959e+2,"","SAN FRANCISCO","CA","94107","US"},
    {"zip",37.371991,-1.22026e+2,"","SUNNYVALE","CA","94085","US"}
  };
  /* 构造视频实例*/
  // 创建一个结构体对象 将type类型设置为对象, 并申请一块地址空间。返回地址
  root = cJSON_CreateObject(); 
  // 创建子结构体value为"Jack (\"Bee\") Nimble",key为"name"。然后连接fmt父结构体
  cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble"));
  // 创建子结构体对象并保存子结构体地址到fmt中,设置key为"type"。然后连接fmt父结构体
  cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject());
  // 创建子结构体value为"rect",key为"type"。然后连接fmt父结构体
  cJSON_AddStringToObject(fmt, "type", "rect");
  // 创建子结构体value为1920,key为"width"。然后连接fmt父结构体
  cJSON_AddNumberToObject(fmt, "width", 1920);
  // 创建子结构体value为1080,key为"height"。然后连接fmt父结构体
  cJSON_AddNumberToObject(fmt, "height", 1080);
  // 创建子结构体value为false,key为"interlace"。然后连接fmt父结构体
  cJSON_AddFalseToObject(fmt, "interlace");
  // 创建子结构体value为24,key为"frame rate"。然后连接fmt父结构体
  cJSON_AddNumberToObject(fmt, "frame rate", 24);
  /* 树结构体解析成json格式字符串,并输出,回收堆区地址*/
  out = cJSON_Print(root);// 将root树结构解析成cjson格式字符串,并存放在堆区,成功返回堆区地址。失败返回NULL
  cJSON_Delete(root);   // 释放root树结构体在堆区的空间
  printf("%s\n", out);  // 打印解析后的字符串
  free(out);        // 释放堆区解析好的字符串空间
  /* 星期数(数组): */
  root = cJSON_CreateStringArray(strings, 7);// 构造星期数树结构(字符串数组)
  /* 树结构体解析成json格式字符串,并输出,回收堆区地址*/
  out = cJSON_Print(root);// 将root树结构解析成cjson格式字符串,并存放在堆区,成功返回堆区地址。失败返回NULL
  cJSON_Delete(root);   // 释放root树结构体在堆区的空间
  printf("%s\n", out);  // 打印解析后的字符串
  free(out);        // 释放堆区解析好的字符串空间
  /* 矩阵 */
  root = cJSON_CreateArray();// 构造矩阵树结构(整型数组)
  for (i = 0; i < 3; i++)
  {
    // 创建一个子结构体数组,并与root连接起来
    cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3));
  }
  // 创建子结构体,并成为root的第1个孩子节点
  // cJSON_ReplaceItemInArray(root,1,cJSON_CreateString("Replacement"));  
  /* 树结构体解析成json格式字符串,并输出,回收堆区地址*/
  out = cJSON_Print(root);// 将root树结构解析成cjson格式字符串,并存放在堆区,成功返回堆区地址。失败返回NULL
  cJSON_Delete(root);   // 释放root树结构体在堆区的空间
  printf("%s\n", out);  // 打印解析后的字符串
  free(out);        // 释放堆区解析好的字符串空间
  /* 走廊 */
  root = cJSON_CreateObject();                          // 创建子结构体(类型为对象) 
  cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject());       // 添加img子对象到root中
  cJSON_AddNumberToObject(img, "Width", 800);                   // 添加子节点到img对象中
  cJSON_AddNumberToObject(img, "Height", 600);                  // 添加子节点到img对象中
  cJSON_AddStringToObject(img, "Title", "View from 15th Floor");          // 添加子节点到img对象中
  cJSON_AddItemToObject(img, "Thumbnail", thm = cJSON_CreateObject());      // 添加thm子对象到img对象中
  cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943");  // 添加子节点到thm对象中
  cJSON_AddNumberToObject(thm, "Height", 125);                  // 添加子节点到thm对象中
  cJSON_AddStringToObject(thm, "Width", "100");                 // 添加子节点到thm对象中
  cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4));        // 添加ids子数组到img对象中
  /* 树结构体解析成json格式字符串,并输出,回收堆区地址*/
  out = cJSON_Print(root);// 将root树结构解析成cjson格式字符串,并存放在堆区,成功返回堆区地址。失败返回NULL
  cJSON_Delete(root);   // 释放root树结构体在堆区的空间
  printf("%s\n", out);  // 打印解析后的字符串
  free(out);        // 释放堆区解析好的字符串空间
  /* 唱片 */
  root = cJSON_CreateArray();                     // 创建子结构体(类型为数组) 
  for (i = 0; i < 2; i++)                       // 二维数组
  {
    cJSON_AddItemToArray(root, fld = cJSON_CreateObject());     // 添加fld子对象到root中
    cJSON_AddStringToObject(fld, "precision", fields[i].precision); // 添加子节点到fld对象中
    cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat);    // 添加子节点到fld对象中
    cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon);   // 添加子节点到fld对象中
    cJSON_AddStringToObject(fld, "Address", fields[i].address);   // 添加子节点到fld对象中
    cJSON_AddStringToObject(fld, "City", fields[i].city);     // 添加子节点到fld对象中
    cJSON_AddStringToObject(fld, "State", fields[i].state);     // 添加子节点到fld对象中
    cJSON_AddStringToObject(fld, "Zip", fields[i].zip);       // 添加子节点到fld对象中
    cJSON_AddStringToObject(fld, "Country", fields[i].country);   // 添加子节点到fld对象中
  }
  // 创建子数组结构体,并成为root的第1个子对象且key==city的value
  // cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root,1),"City",cJSON_CreateIntArray(ids,4));
  /* 树结构体解析成json格式字符串,并输出,回收堆区地址*/
  out = cJSON_Print(root);// 将root树结构解析成cjson格式字符串,并存放在堆区,成功返回堆区地址。失败返回NULL
  cJSON_Delete(root);   // 释放root树结构体在堆区的空间
  printf("%s\n", out);  // 打印解析后的字符串
  free(out);        // 释放堆区解析好的字符串空间
}
#if 1
int main(int argc, const char* argv[]) 
{
  /* 一堆 cjson */
  char text1[] = "{\n\"name\": \"Jack (\\\"Bee\\\") Nimble\", \n\"format\": {\"type\":       \"rect\", \n\"width\":      1920, \n\"height\":     1080, \n\"interlace\":  false,\"frame rate\": 24\n}\n}";
  char text2[] = "[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]";
  char text3[] = "[\n    [0, -1, 0],\n    [1, 0, 0],\n    [0, 0, 1]\n ]\n";
  char text4[] = "{\n   \"Image\": {\n      \"Width\":  800,\n      \"Height\": 600,\n      \"Title\":  \"View from 15th Floor\",\n     \"Thumbnail\": {\n        \"Url\":    \"http:/*www.example.com/image/481989943\",\n       \"Height\": 125,\n        \"Width\":  \"100\"\n     },\n      \"IDs\": [116, 943, 234, 38793]\n   }\n }";
  char text5[] = "[\n  {\n   \"precision\": \"zip\",\n   \"Latitude\": 37.7668,\n  \"Longitude\": -122.3959,\n   \"Address\":   \"\",\n  \"City\":      \"SAN FRANCISCO\",\n   \"State\":     \"CA\",\n  \"Zip\":       \"94107\",\n   \"Country\":   \"US\"\n   },\n  {\n   \"precision\": \"zip\",\n   \"Latitude\":  37.371991,\n   \"Longitude\": -122.026020,\n   \"Address\":   \"\",\n  \"City\":      \"SUNNYVALE\",\n   \"State\":     \"CA\",\n  \"Zip\":       \"94085\",\n   \"Country\":   \"US\"\n   }\n   ]";
  /* 字符串方式调用 */
  doit(text1);
  doit(text2);
  doit(text3);
  doit(text4);
  doit(text5);
  /* 从文件中读取字符串文本 */
/*  dofile("../../tests/test2"); */
/*  dofile("../../tests/test3"); */
/*  dofile("../../tests/test4"); */
/*  dofile("../../tests/test5"); */
  /* Now some samplecode for building objects concisely: */
   create_objects();
  return 0;
}
#endif


由于笔者水平有限,可能会有一些错误欢迎大佬帮忙勘正。

目录
相关文章
|
4月前
|
设计模式 存储 Python
Python元类大揭秘:从理解到应用,一步步构建你的编程帝国
【7月更文挑战第6天】Python元类是创建类的对象的基石,允许控制类的生成过程。通过自定义元类,可在类定义时动态添加方法或改变行为。
78 0
|
6月前
|
存储 Rust Go
Python 潮流周刊#16:优雅重要么?如何写出 Pythonic 的代码?
Python 潮流周刊#16:优雅重要么?如何写出 Pythonic 的代码?
65 0
|
3月前
|
Rust 安全 程序员
Rust 语言的防错机制太惊人了!安全编码从此不再是难题,快来一探究竟!
【8月更文挑战第31天】《安全编码原则:Rust 语言中的防错机制》探讨了代码安全的重要性,并详细介绍了Rust语言如何通过内存安全模型、所有权与借用规则等特性,在编译阶段检测并阻止潜在错误,如缓冲区溢出和悬空指针。文章还讨论了类型安全、边界检查等其他安全特性,并提出了遵循不可变引用、避免裸指针及充分测试等实用编码原则,以进一步提升代码质量和安全性。随着Rust在软件开发中的应用日益广泛,掌握其安全编码原则变得尤为重要。
55 0
|
3月前
|
机器学习/深度学习 Rust 编译器
神秘编程语言 Rust 背后究竟隐藏着怎样的生态宝藏?框架、工具链与社区资源大揭秘!
【8月更文挑战第31天】Rust 语言凭借卓越性能与内存安全性吸引了众多开发者。其生态系统包括多种框架(如 Actix-web、Rocket 和 Warp)、强大的工具链(如包管理器 Cargo 和高效编译器)以及丰富的社区资源。Cargo 简化了项目管理,编译器提供详尽错误信息并支持增量编译,而活跃的社区则为学习与交流提供了广阔平台,涵盖官方文档、博客、论坛及大量 GitHub 开源项目。随着更多开发者的加入,Rust 生态系统将持续繁荣发展。
63 0
|
5月前
|
程序员
老程序员分享:lua类实现
老程序员分享:lua类实现
25 2
|
存储 JSON JavaScript
cJSON开源项目详细解剖1
cJSON开源项目详细解剖
226 0
|
6月前
|
JavaScript 前端开发 开发者
CommonJS 模块编程(新思路方便复习笔记)
CommonJS 模块编程(新思路方便复习笔记)
56 0
cJSON开源项目详细解剖2
cJSON开源项目详细解剖2
79 0
|
存储 人工智能 算法
C++ Primer Plus 第6版 读书笔记(7)第 7 章 函数——C++的编程模块
乐趣在于发现。仔细研究,读者将在函数中找到乐趣。C++自带了一个包含函数的大型库(标准 ANSI 库加上多个 C++类),但真正的编程乐趣在于编写自己的函数;另一方面,要提高编程效率,本章和第 8 章介绍如何定义函数、给函数传递信息以及从函数那里获得信息。
164 0