cJSON是一个轻量级的C语言JSON解析库,可以方便地将C语言数据结构转换为JSON格式,或者将JSON数据解析为C语言数据结构。下面介绍如何使用cJSON来封装和解析C语言中的结构体。
基本用法
1. 安装cJSON
首先需要获取cJSON库,可以从GitHub仓库下载,或者通过包管理器安装。
2. 包含头文件
#include "cJSON.h"
结构体转JSON示例
假设我们有以下结构体:
typedef struct {int id;char name[50];double price;int stock;
} Product;
将结构体转换为JSON
cJSON* product_to_json(const Product* product) {// 创建JSON对象cJSON* json = cJSON_CreateObject();if (json == NULL) {return NULL;}// 添加各个字段到JSON对象cJSON_AddNumberToObject(json, "id", product->id);cJSON_AddStringToObject(json, "name", product->name);cJSON_AddNumberToObject(json, "price", product->price);cJSON_AddNumberToObject(json, "stock", product->stock);return json;
}
使用示例
Product p = {1, "Laptop", 999.99, 10};
cJSON* json = product_to_json(&p);// 获取JSON字符串
char* json_str = cJSON_Print(json);
printf("JSON: %s\n", json_str);// 释放资源
free(json_str);
cJSON_Delete(json);
JSON转结构体示例
将JSON解析为结构体
int json_to_product(const cJSON* json, Product* product) {if (json == NULL || product == NULL) {return -1;}// 从JSON对象中获取各个字段cJSON* id = cJSON_GetObjectItemCaseSensitive(json, "id");cJSON* name = cJSON_GetObjectItemCaseSensitive(json, "name");cJSON* price = cJSON_GetObjectItemCaseSensitive(json, "price");cJSON* stock = cJSON_GetObjectItemCaseSensitive(json, "stock");if (!cJSON_IsNumber(id) || !cJSON_IsString(name) || !cJSON_IsNumber(price) || !cJSON_IsNumber(stock)) {return -1;}// 填充结构体product->id = id->valueint;strncpy(product->name, name->valuestring, sizeof(product->name) - 1);product->name[sizeof(product->name) - 1] = '\0';product->price = price->valuedouble;product->stock = stock->valueint;return 0;
}
使用示例
const char* json_str = "{\"id\":2,\"name\":\"Smartphone\",\"price\":599.99,\"stock\":20}";
cJSON* json = cJSON_Parse(json_str);Product p;
if (json_to_product(json, &p) == 0) {printf("Product: ID=%d, Name=%s, Price=%.2f, Stock=%d\n", p.id, p.name, p.price, p.stock);
}cJSON_Delete(json);
处理嵌套结构体
对于更复杂的嵌套结构体,例如:
typedef struct {int order_id;char customer[100];Product products[10];int product_count;
} Order;
嵌套结构体转JSON
cJSON* order_to_json(const Order* order) {cJSON* json = cJSON_CreateObject();cJSON_AddNumberToObject(json, "order_id", order->order_id);cJSON_AddStringToObject(json, "customer", order->customer);// 创建产品数组cJSON* products = cJSON_AddArrayToObject(json, "products");for (int i = 0; i < order->product_count; i++) {cJSON* product_json = product_to_json(&order->products[i]);cJSON_AddItemToArray(products, product_json);}return json;
}
JSON转嵌套结构体
int json_to_order(const cJSON* json, Order* order) {cJSON* order_id = cJSON_GetObjectItemCaseSensitive(json, "order_id");cJSON* customer = cJSON_GetObjectItemCaseSensitive(json, "customer");cJSON* products = cJSON_GetObjectItemCaseSensitive(json, "products");if (!cJSON_IsNumber(order_id) || !cJSON_IsString(customer) || !cJSON_IsArray(products)) {return -1;}order->order_id = order_id->valueint;strncpy(order->customer, customer->valuestring, sizeof(order->customer) - 1);order->customer[sizeof(order->customer) - 1] = '\0';order->product_count = 0;cJSON* product;cJSON_ArrayForEach(product, products) {if (order->product_count >= 10) break;if (json_to_product(product, &order->products[order->product_count]) == 0) {order->product_count++;}}return 0;
}
内存管理注意事项
-
使用
cJSON_Print()
返回的字符串需要使用free()
释放 -
使用
cJSON_Parse()
创建的cJSON对象需要使用cJSON_Delete()
释放 -
数组和对象中的项目会被自动删除,不需要单独释放
错误处理
在实际应用中,应该添加适当的错误处理:
cJSON* json = cJSON_Parse(json_str);
if (json == NULL) {const char* error_ptr = cJSON_GetErrorPtr();if (error_ptr != NULL) {fprintf(stderr, "Error before: %s\n", error_ptr);}return -1;
}
通过以上方法,可以方便地在C语言中使用cJSON库来序列化和反序列化复杂的数据结构体。