设备工作中,经常会使用一些配置文件,用来指导某些用户配置。我们手机里面的配置就是最常见的例子。简单的配置文件可能没有什么规则,按照使用习惯生成读取就行。对于稍微多一点的配置,就需要按照一定的规则了,且要尽可能符合人类读取和识别的习惯。
常见的有xml和json配置文件,这2种配置文件应用都很广泛,都都有成熟的库进行支持。
下面大致来进行二者的比较:
维度 | JSON | XML |
---|---|---|
结构与语法 | 键值对形式,类似编程语言中的对象。 示例:{"name": "Alice", "age": 30} |
嵌套标签结构,类似文档格式。 示例:
|
可读性 | 更简洁紧凑,易于人工阅读和编写。 | 标签冗余度高,但层次结构更清晰(尤其复杂数据)。 |
解析性能 | 解析速度更快,数据体积小(节省带宽)。 | 解析较慢(尤其大文件),占用更多内存和带宽。 |
扩展性 | 灵活性高,但缺乏复杂验证机制。 | 支持命名空间、DTD/XSD验证,适合复杂数据结构和严格约束。 |
安全性 | 相对更安全(但仍需防范注入攻击)。 | 存在XML注入等风险,需额外防护。 |
数据类型支持 | 原生支持数组、布尔值、null 等。 |
需通过标签属性模拟复杂类型,灵活性较低。 |
应用场景推荐:
场景 | 推荐格式 | 理由 |
---|---|---|
Web API & 移动应用 | ✅ JSON | 轻量、解析快,完美契合RESTful API和前后端分离架构。 |
企业级系统集成 | ✅XML | 需严格数据验证(如XSD)、命名空间防冲突(如多部门数据合并)。 |
实时数据传输 | ✅ JSON | 低延迟需求(如物联网传感器数据)。 |
文档存储与发布 | ✅XML | 适合电子书、标准化报告(如PubMed期刊)。 |
配置文件 | ⚖视复杂度定 | 简单配置用JSON(如VSCode设置),复杂依赖用XML(如Spring Bean定义)。 |
从上面可以看到,json 适合轻量应用,本次就简单使用 cJSON
源码进行简单的介绍 JSON 配置文件使用。
CJSON
源码请到个人 gitee
仓库进行下载
在 cJSON.h
中声明了 cjson
对象的数据结构,如下:
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
struct cJSON *next
, *prev
作用:构成双向链表,指向同一层级的下一个/上一个节点。
适用场景:遍历数组(Array
)或对象(Object
)中的同级元素时使用。
示例:若解析 [1, “a”, true] 三个元素通过 next/prev 进行连接。
struct cJSON *child
作用:指向子节点(下一层级)。
适用场景:仅当节点类型为 cJSON_Object
(对象)或 cJSON_Array
(数组)时有效。
示例:对象 {“name”: “John”}中,键 "name"对应的值节点是对象的子节点。
int type
作用:标识节点类型,以位标志(bit-flag)存储。需通过cJSON_IsXxx()函数判断类型
常见类型值:
宏定义 | 值 | 说明 |
---|---|---|
cJSON_False |
0 | 布尔值 false |
cJSON_True |
1 | 布尔值 true |
cJSON_NULL |
2 | null 值 |
cJSON_Number |
3 | 数值(整数或浮点数) |
cJSON_String |
4 | 字符串 |
cJSON_Array |
5 | 数组 |
cJSON_Object |
6 | 对象 |
cJSON_Raw |
7 | 原始 JSON 字符串(未解析) |
cJSON_IsReference |
256 | 子节点或值为引用(不释放内存) |
cJSON_StringIsConst |
512 | 键名是字面量(不释放内存) |
char *valuestring
作用:存储字符串类型(cJSON_String
)或原始 JSON(cJSON_Raw
)的值。
注意:以 \0 结尾,需通过 cJSON_IsString()
验证类型后使用。
int valueint
与 double valuedouble
作用:存储数值类型(cJSON_Number
)的值。
注意:
数值会同时存储在 valueint
和 valuedouble
中。
若数值超出整型范围,``valueint会被设为
INT_MAX或
INT_MIN`。
建议通过cJSON_GetNumberValue()
获取值。
char *string
{"key": value}
中的 "key"
)cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。number
- 要添加的双精度浮点数。cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。string
- 要添加的C字符串。cJSON_AddTrueToObject(cJSON * const object, const char * const name)
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。cJSON_AddFalseToObject(cJSON * const object, const char * const name)
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。boolean
- 要添加的布尔值,非零表示true,零表示false。cJSON_AddObjectToObject(cJSON * const object, const char * const name)
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。cJSON_AddArrayToObject(cJSON * const object, const char * const name)
object
- 目标JSON对象。name
- 要添加的键的名称(C字符串)。cJSON_Parse(const char *value)
value
- 包含JSON数据的C字符串。cJSON_GetObjectItem(const cJSON *object, const char *string)
object
- 目标JSON对象。string
- 要获取值的键的名称(C字符串)。cJSON_GetArrayItem(const cJSON *array, int index)
array
- 目标JSON数组。index
- 要获取的元素的索引(从0开始)。cJSON_Print(const cJSON *item)
具体实例参考 本人 gitee
cjson使用 中 src
和 include
目录,大致功能是先简单生成一个.json
文件,然后在读取内容值。