首页 > 其他分享 >【大一C语言项目】Cjson的认识与实现(二)

【大一C语言项目】Cjson的认识与实现(二)

时间:2022-11-25 20:01:12浏览次数:76  
标签:item Cjson void object C语言 char cJSON 大一 extern


【大一C语言项目】Cjson的认识与实现(二)

参考资料:
​​​哔哩哔哩CJson开源库使用及注意事项​​​​CJson开源项目下载地址​​​​cJSON源码刨析​

一、使用Cjson库

下载CJSON:​​CJson开源项目下载地址​​ 我们解压后看到cJSON.h和cJSON.c两个文件,我们把这两个文件加入到项目中

【大一C语言项目】Cjson的认识与实现(二)_#define


【大一C语言项目】Cjson的认识与实现(二)_数组_02


序列化

序列化:把对象转化为可传输的字节序列过程称为序列化。
反序列化:把字节序列还原为对象的过程称为反序列化。

cJSON要实现的主要是是反序列化的过程,在c语言程序中利用相关库函数调用将字节序列还原成对象并打印输出的过程

二、Cjson.h文件源码分析

源码

/*
Copyright (c) 2009 Dave Gamble

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef cJSON__h
#define cJSON__h

#ifdef __cplusplus
extern "C"
{
#endif

/* cJSON Types:*/
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6

#define cJSON_IsReference 256
#define cJSON_StringIsConst 512

/* 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;

typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;

/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);


/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);

/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr(void);

/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);

/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);

/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);

/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);

/* Update array items. */
extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);

/* Duplicate a cJSON item */
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */

/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);

extern void cJSON_Minify(char *json);

/* Macros for creating things quickly. */
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))

/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))

#ifdef __cplusplus
}
#endif

#endif

逐段分析与翻译

预处理

#ifndef cJSON__h
#define cJSON__h//定义cJSON__h头文件

#ifdef __cplusplus//extern "C"的主要作用就是为了能够正确实现C++代码调用其他C语言代码
extern "C"
{
#endif

cJSON数据类型

/* cJSON Types:*/ 
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6

#define cJSON_IsReference 256//暂时不知道是干嘛的
#define cJSON_StringIsConst 512//字符串大小常量?

/*使用结构体cJSON结构体表示键值对*/
typedef struct cJSON {
//双向链表来实现
struct cJSON *next,*prev;//数组/对象链,next和prev应该是同一级的
struct cJSON *child;//用来实现对象/数组嵌套
int type;//数据类型
char *valuestring;//值为字符串类型
int valueint;//值为整型
double valuedouble; //值为浮点数类型
char *string;//键名,区分valuestring
} cJSON;

参考这位​​大佬的博客​

【大一C语言项目】Cjson的认识与实现(二)_#define_03


内存操作

typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);//这两个内存相关操作细节不是很清楚
void (*free_fn)(void *ptr);
} cJSON_Hooks;

/* 让cJSON数据类型能够支持 malloc, realloc and free 这些操作 */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);//extern void 函数外部声明,使得可以多文件调用

​size_t相关知识点​​ size_t和unsigned int有所不同,size_t的取值range是目标平台下最大可能的数组尺寸,貌似可以增加不同平台的可移植性

基本操作函数声明

cJSON整体操作,查询,打印,删除

/* 提供一个JSON块,然后返回一个你可以查询的cJSON对象。完成后调用cJSON_Delete. 应该是解析用的,把json数据打包成cJSON格式*/
extern cJSON *cJSON_Parse(const char *value);
/* 将一个cJSON实体渲染解析成文本打印出来,并且在完成的时候释放char* */
extern char *cJSON_Print(cJSON *item);
/* 将一个cJSON实体渲染解析成文本没有格式的打印出来,并且完成的时候释放char* */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* 使用缓冲策略将一个cJSON实体渲染成文本,prebuffer是对最终大小的猜测,猜得好可以减少重新分配. fmt=0 表示无格式 unformatted, fmt=1 表示有格式 formatted */
extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
/* 删除一个cJSON实体和他所有子实体 */
extern void cJSON_Delete(cJSON *c);

对象/数组获取信息

/* 返回对象/数组大小. */
extern int cJSON_GetArraySize(cJSON *array);
/* 从数组中获取元素,如果不成功返回NULL */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* 从对象中获取string,不区分大小写 */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

报错

/* 报错,用于分析失败的解析。这将返回一个指向解析错误的指针。你可能需要回溯几个字符来理解它,当cJSON_Parse()成功时返回0。*/
extern const char *cJSON_GetErrorPtr(void);

创建

/* cJSON数据类型创建 */
extern cJSON *cJSON_CreateNull(void);//申请一个空的cJSON数据结构内存空间,然后将其成员type置为cJSON_NULL类型。
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);//采用const char * string
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);
/* 创建计数数组 */
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);

添加item

/* 添加item到指定数组或对象 */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* 当字符串绝对是const(即一个字面意思,或好比),并且一定会在cJSON对象中存在时,使用这个。 */

删除item

/* 从指定数组或对象中删除元素*/
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);

更新替换插入item

/* 更新数组元素. */
extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* 原有数组右移 */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);/* 替换数组指定位置元素 */
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);/* 替换对象指定名字元素 */

cJSON复制粘贴

/* 复制一个cJSON*/
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* 复制将在新的内存中创建一个新的、与你传递的cJSON项目相同的项目,该项目将在需要被释放。当recurse!=0时,它将复制任何连接到项目的子项目。item->next和->prev指针在从Duplicate返回时始终为零。 */

/*ParseWithOpts允许你请求(并检查)JSON是null terminated,并检索到解析的最后一个字节的指针。 */
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);

暂时不清楚的

extern void cJSON_Minify(char *json);

宏来快速创建

#define cJSON_AddNullToObject(object,name)    cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
/*  当分配一个整数值时,也需要将其传给valuedouble. */
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))

小结

  1. 多文件编译我们可以创建一个头文件把所有函数都用extern声明,方便调用,而且很清晰。很适合一堆函数的情况
  2. cJSON处理重点在于对象和数组类型数据的处理各种增删改查以及扩展操作
  3. 可以使用宏来简化语法
  4. JSON数据格式可以自定义一个结构体使用双向链表来实现。
    为何使用双向链表?​​数组,单向链表,双向链表区别​​


标签:item,Cjson,void,object,C语言,char,cJSON,大一,extern
From: https://blog.51cto.com/u_15891800/5887714

相关文章

  • [NEFU ACM大一暑假集训 解题报告]字典树
    [NEFUACM大一暑假集训解题报告]字典树题目A-L语言多模式匹配,AC自动机建立Trie图。不过这个题数据量很小,貌似可以暴力建立跳转关系,加上标记处理即可。对于样例的AC自动......
  • [NEFU ACM大一暑假集训 解题报告]前缀和与差分
    [NEFUACM大一暑假集训解题报告]前缀和与差分题量略大,所以解题报告和fjy大佬分了一下工由我负责A-K部分题解(不是AK部分题解啊,哈哈)后半部分题解(LM+R~V+XYZ)由fjy大佬发布......
  • [NEFU ACM大一暑假集训 解题报告]尺取法
    [NEFUACM大一暑假集训解题报告]尺取法前四题为例题,学长讲过了,直接贴代码了。题谱题目A-Subsequence求总和>=s的最短区间#include<cstdio>#include<cstdlib>#include<cma......
  • C语言基础
    (1)栈(stack):由编译器进行管理,自动分配和释放,存放函数调用过程中的各种参数、局部变量、返回值以及函数返回地址。操作方式类似数据结构中的栈。(2)堆(heap):用于程序动态申请分配......
  • [Object-C语言随笔之一]Mac os 下搭建iOS开发环境
    ​​ 李华明Himi ​​​原创,转载务必在明显处注明 从这一章开始,Himi将一步一步的带大家走进Iphone4的开发,当然开发语言则不再是Java,而是Objective-C,简单来说是C的变种......
  • [Object-C语言随笔之四]创建视图并绘制简单图形
    ​​ 李华明Himi ​​​原创,转载务必在明显处注明这段时间N忙,没办法,创业公司,当然抽时间也仍然再自学ios~OK,基础的语言基础,我就不多说了,从今天开始直接写游戏开发部分......
  • C语言 | 三子棋游戏
    C语言实现《三子棋》小游戏1-需求分析1️⃣游戏规则介绍:双方轮流下子,直到三个子连成一条线,横、竖、斜线都可以,谁先达到这个要求就获胜,或者说棋盘满了,则游戏平局结束[1]......
  • 喝汽水--C语言
    问题:喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水?分析:1.20元肯定可以喝20瓶2.2个空瓶可以换一瓶汽水,则剩下瓶子数量:empty/2+empty%2empty/2:表示成功换汽水的......
  • [c语言基础]如何判断素数
    素数又称质数。所谓素数是指除了1和它本身以外,不能被任何整数整除的数,例如17就是素数,因为它不能被2~16的任一整数整除。思路1:因此判断一个整数m是否是素数,只需把m被......
  • C语言学习:【函数】
    C语言中的函数名是一个指向函数方法地址,这意味着可以将函数名作为值传递给指针,在这两个的前提下于是就有了指针函数和函数指针1.指针函数指针函数既是返回值为指针的函数......