介绍 JSON:https://www.json.org/json-zh.html
cJSON Github:https://github.com/DaveGamble/cJSON
JSON在线解析工具:http://www.json.org.cn/tools/JSONEditorOnline/index.htm
cJson库中提供了非常多接口函数供我们使用,这里记录cJSON与C语言的文件操作的示例。
1. 读取json文件
从json中读取文件,返回包含文件内容的字符串,注意使用该函数后需要手动释放。
/* 读取json文件 */
const char* ReadJson(const char* filename)
{
FILE* fp = NULL;
long len = 0;
char* data = NULL;
fp = fopen(filename, "rb"); /* 打开文件 */
fseek(fp, 0, SEEK_END); /* 设置文件指针位置——SEEK_END,文件末尾 */
len = ftell(fp); /* 计算当前文件指针位置到文件起始位置的偏移 */
fseek(fp, 0, SEEK_SET); /* 设置文件指针位置——SEEK_SET,文件起始位置 */
data = (char*)malloc(len + 1);/* 申请空间存放数据,读取文件数据存储至该buff中 */
fread(data, 1, len, fp); /* 从文件中读取数据,存放在data所指向的buff中 */
fclose(fp); /* 关闭文件指针 */
//free(data); /* 释放data所指向的malloc空间 */
return data;
}
2. 保存文件
- 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。即将我们对象中的数据转化为易于传输的字节流形式。
- 反序列化,是序列化的逆过程。即,将字符串流转换为对象。
使用序列化的 json 数据构建 json 对象需要使用 cJSON_Parse()
函数。
/* 保存 普通字符串 到文本文件 */
void SaveText(const char* text, const char* name)
{
FILE* fp = fopen(name, "w");
if (NULL != fp)
{
fwrite(text, strlen(text), 1, fp); /* 保存到文件 */
// fputs(buff,fp);
fclose(fp); /* 关闭文件指针 */
}
else perror("open text.json error!\n");
}
/* 将文本处理成json格式后保存 */
void Save_TextToJSON(const char *text, const char* name)
{
cJSON* json;
json = cJSON_Parse(text); /* 从json字符串中得到cjson对象 */
if (!json) {
printf("Error before: [%s]\n", cJSON_GetErrorPtr());
}
char* buff = cJSON_Print(json); /* 将json对象转化为打印的格式 */
SaveText(buff, name); /* 保存到文件 */
cJSON_Delete(json); /* 释放json对象 */
free(buff); /* 释放buff字符串 */
}
测试代码
#include <stdio.h>
#include <stdlib.h>
#include "cJSON.h"
#pragma warning(disable:4996)
/* 将文本解析为JSON格式,并打印 */
void Show(char *text)
{
cJSON *json = cJSON_Parse(text); /* 从json字符串中得到cjson对象 */
if (!json) {
printf("Error before: [%s]\n",cJSON_GetErrorPtr());
}
char* out=cJSON_Print(json);/* 将json对象转化为打印的格式 */
printf("%s\n",out); /* 将格式化的json数据打印在屏幕上 */
cJSON_Delete(json); /* 释放json对象 */
free(out); /* 释放out字符串 */
}
/* 读取json文件 */
const char* ReadJson(const char* filename)
{
FILE* fp = NULL;
long len = 0;
char* data = NULL;
fp = fopen(filename, "r"); /* 打开文件 */
fseek(fp, 0, SEEK_END); /* 设置文件指针位置——SEEK_END,文件末尾 */
len = ftell(fp); /* 计算当前文件指针位置到文件起始位置的偏移 */
fseek(fp, 0, SEEK_SET); /* 设置文件指针位置——SEEK_SET,文件起始位置 */
data = (char*)malloc(len + 1);/* 申请空间存放数据,读取文件数据存储至该buff中 */
fread(data, 1, len, fp); /* 从文件中读取数据,存放在data所指向的buff中 */
fclose(fp); /* 关闭文件指针 */
//free(data); /* 释放data所指向的malloc空间 */
return data;
}
/* 保存 普通字符串 到文本文件 */
void SaveText(const char* text, const char* name)
{
FILE* fp = fopen(name, "w");
if (NULL != fp)
{
fwrite(text, strlen(text), 1, fp); /* 保存到文件 */
// fputs(buff,fp);
fclose(fp); /* 关闭文件指针 */
}
else perror("open text.json error!\n");
}
/* 将文本处理成json格式后保存 */
void Save_TextToJSON(const char *text, const char* name)
{
cJSON* json;
json = cJSON_Parse(text); /* 从json字符串中得到cjson对象 */
if (!json) {
printf("Error before: [%s]\n", cJSON_GetErrorPtr());
}
char* buff = cJSON_Print(json); /* 将json对象转化为打印的格式 */
SaveText(buff, name); /* 保存到文件 */
cJSON_Delete(json); /* 释放json对象 */
free(buff); /* 释放buff字符串 */
}
int main ()
{
char text[] =
"{\"name\":\"JSON中国\",\"url\":\"http://www.json.org.cn\",\"page\":88,\"isNonProfit\":true,\"address\":{\"street\":\"浙大路38号.\",\"city\":\"浙江杭州\",\"country\":\"中国\"},\"links\":\
[{\"name\":\"Google\",\"url\":\"http://www.google.com\"},{\"name\":\"Baidu\",\"url\":\"http://www.baidu.com\"},{\"name\":\"SoSo\",\"url\":\"http://www.SoSo.com\"}]}";
//printf("%s\n", text); // 输出text内容到屏幕
SaveText(text, "text.txt"); // 保存text内容到文本
//Show(text); // 将text内容,以json格式的“视图”打印
Save_TextToJSON(text, "text.json");// 解析json字符串,并保存为json格式的文件
// 读取json文件,data是json格式化数据
const char* data = ReadJson(".\\text.json");// 路径使用 '/'或'\\'都可以 //free
cJSON* pjson = cJSON_Parse(data); // 使用json数据构建cJSON对象
char* p = cJSON_Print(pjson); // free
printf("%s\n", p);
const char* out = cJSON_PrintUnformatted(pjson);// 不使用格式化的打印 // free
printf("%s\n", out);
cJSON_Delete(pjson);
free(data);
free(p);
free(out);
return 0;
}
cJSON头文件中提供的接口函数。
#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
/* 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);
/* 提供一个JSON块,这会返回一个可以查询的cJSON对象。完成后调用cJSON Delete */
extern cJSON* cJSON_Parse(const char* value);
/* 将一个cJSON实体渲染为文本以便传输/存储。完成时释放char* */
extern char* cJSON_Print(cJSON* item);
/* 将cJSON实体呈现为文本以进行传输/存储,而无需进行任何格式设置。 完成后释放字符*。 */
extern char* cJSON_PrintUnformatted(cJSON* item);
/* 删除一个cJSON实体和所有子实体。 */
extern void cJSON_Delete(cJSON* c);
/* 返回数组(或对象)中项目的数量。 */
extern int cJSON_GetArraySize(cJSON* array);
/* 从数组“array”中检索项目编号“item”。如果不成功则返回NULL。 */
extern cJSON* cJSON_GetArrayItem(cJSON* array, int item);
/* 从object中获取item "string"。不区分大小写。 */
extern cJSON* cJSON_GetObjectItem(cJSON* object, const char* string);
/* 用于分析失败的分析。 这将返回一个指向解析错误的指针。 您可能需要回顾一些字符才能理解它。
在cJSON_Parse()返回0时定义。当cJSON_Parse()成功时为0。 */
extern const char* cJSON_GetErrorPtr(void);
/* 这些调用创建一个适当类型的cJSON项。 */
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);
/* 这些实用程序创建一个计数项数组。 */
extern cJSON* cJSON_CreateIntArray(int* numbers, int count);
extern cJSON* cJSON_CreateFloatArray(float* numbers, int count);
extern cJSON* cJSON_CreateDoubleArray(double* numbers, int count);
extern cJSON* cJSON_CreateStringArray(const char** strings, int count);
/* 将项目追加到指定的数组/对象。 */
extern void cJSON_AddItemToArray(cJSON* array, cJSON* item);
extern void cJSON_AddItemToObject(cJSON* object, const char* string, cJSON* item);
/* 将对项目的引用附加到指定的数组/对象。 当您要将现有的cJSON添加到新的cJSON,但又不想破坏现有的cJSON时,请使用此选项。 */
extern void cJSON_AddItemReferenceToArray(cJSON* array, cJSON* item);
extern void cJSON_AddItemReferenceToObject(cJSON* object, const char* string, 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);
/* 更新数组项。 */
extern void cJSON_ReplaceItemInArray(cJSON* array, int which, cJSON* newitem);
extern void cJSON_ReplaceItemInObject(cJSON* object, const char* string, cJSON* newitem);
/* 复制一个cJSON项 */
extern cJSON* cJSON_Duplicate(cJSON* item, int recurse);
/* Duplicate将在新的内存中创建一个与你传递的cJSON项相同的新cJSON项需要被释放。递归!=0时,它将复制连接到该项目的任何子节点。
在从Duplicate返回时,item->next和->prev指针总是0。 */
/* ParseWithOpts允许您要求(并检查)JSON是否以null结尾,并检索指向已解析的最终字节的指针。 */
extern cJSON* cJSON_ParseWithOpts(const char* value, const char** return_parse_end, int require_null_terminated);
/* 用于快速创建事物的宏。 */
#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))
/* 当分配一个整数值时,它也需要传播到valueddouble。 */
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#ifdef __cplusplus
}
#endif
#endif