C语言依赖于cJSON的结构体反射序列化库cJSONx

C语言JSON序列化反序列化工具库

cJSONx是依赖于cJSON解析库的二次封装库,实现快速、灵活地对在C语言结构体(struct)与JSON字符串之间转换

cJSONx GIT仓库传送门

1. 前言

  C语言是嵌入式领域为数不多的选择之一,现代嵌入式应用当中又有很多业务逻辑会涉及到JSON转换的需求,此工具库依赖于C语言JSON解析库cJSON,编写cJSONx的目的是实现相对优雅地对JSON字符串进行正反序列化。

2 参考

本工具库实现参考了

3 实现目标

  cJSONx的目标就是最大化简化相关业务逻辑代码,实现的模式基本上就是参照Java谷歌GSON,通过类反射机制进行数据读写,使用@Expose@SerializedName等注解实现一些基本的正反序列化规定,关于GSON的使用不再赘述。

4 使用简介

  cJSONx参考了一部分cson的实现,做了一些拓展和完善,在宏API设计上进行了完善。
  cJSONx支持对c语言所有基本类型的反射,包括不同长度的整型和float、double两种浮点类型。
  cJSONx支持ptr反射和preallocated反射,使用时选用不同的来声明当前field是否需要申请空间,ptr反射会通过依赖库cJSON中cJSON_Hooks指定的内存申请、释放函数进行内存分配释放操作(默认为标准库的mallocfree),preallocated反射则用于静态内存field。

4.1 宏API

注意,函数名字中不带有ptr的声明均用于静态内存声明。

4.1.1 基础类型反射

__cjsonx_int(type, field) // 对应 1,2,4,8任意字节长度整型
__cjsonx_real(type, field) // 对应 float 或者 double
__cjsonx_bool(type, field) // 对应 bool, 或者任意整型
__cjsonx_str(type, field) // 对应字符数组 char c[20]
__cjsonx_str_ptr(type, field) // 对应字符指针 char* str
__cjsonx_object(type, field, reflect) // 对应结构体
__cjsonx_object_ptr(type, field, reflect) // 对应结构体指针

4.1.2 静态Array反射

__cjsonx_array_int(type, field, item_count_field) // 对应任意整型数组
__cjsonx_array_real(type, field, item_count_field) // 对应任意浮点型数组
__cjsonx_array_bool(type, field, item_count_field) // 对应bool数组或者整型数组
__cjsonx_array_str_ptr(type, field, item_count_field) // 对应字符指针数组, char* strs[10]
__cjsonx_array_str(type, field, item_count_field) // 对应 char[20][50]
__cjsonx_array_object(type, field, item_count_field, refelct) // 对应结构体数组

4.1.3 指针(动态内存)Array反射

__cjsonx_array_ptr_int(type, field, item_count_field) // 8/16/32/64位int* arr_i
__cjsonx_array_ptr_real(type, field, item_count_field) // float/double* arr_d 
__cjsonx_array_ptr_bool(type, field, item_count_field) // bool* arr_b
__cjsonx_array_ptr_str_ptr(type, field, item_count_field) // char** strs
__cjsonx_array_ptr_object(type, field, item_count_field, refelct) // 结构体指针

4.1.4 扩展注解的反射

__cjsonx_int_ex(type, field, annotations...)
__cjsonx_real_ex(type, field, annotations...)
__cjsonx_bool_ex(type, field, annotations...)
__cjsonx_str_ex(type, field, annotations...)
__cjsonx_str_ptr_ex(type, field, annotations...)
__cjsonx_object_ex(type, field, reflect, annotations...)
__cjsonx_object_ptr_ex(type, field, reflect, annotations...)

__nullable(__val) // 注解此field不可为空
__deserialized(__val) // 注解此field是否反序列化
__serialized(__val) // 注解此field是否序列化
__serialized_name(__name) // 注解此field序列化名
...

4.1.5 正反序列化API


/**
 * Convert Json string to struct
 * 
 * @param jstr Json string
 * @param output Struct address
 * @param tbl Reflection table
 * @return Error code 
 */
int cjsonx_str2struct(const char* jstr, void* output, const cjsonx_reflect_t* tbl);

/**
 * Convert Json string with length to struct
 * 
 * @param jstr Json string preallocated
 * @param len Buffer length
 * @param output Struct address
 * @param tbl Reflection table
 * @return Error code 
 */
int cjsonx_nstr2struct(const char* jstr, size_t len, void* output, const cjsonx_reflect_t* tbl);

/**
 * Convert cJSON object to struct
 * 
 * @param jo Json object
 * @param output Struct address
 * @param tbl Reflection table
 * @return Error code 
 */
int cjsonx_obj2struct(cJSON* jo, void* output, const cjsonx_reflect_t* tbl);

/**
 * Convert struct to json (string allocated)
 * 
 * @param jstr Pointer to place string address
 * @param input Struct address
 * @param tbl Reflection table
 * @return error code
 */
int cjsonx_struct2str(char** jstr, void* input, const cjsonx_reflect_t* tbl);

/**
 * Convert struct to json (char buffer preallocated)
 * 
 * @param jstr String buffer
 * @param size Buffer size
 * @param input Struct address
 * @param tbl Reflection table
 * @return error code
 */
int cjsonx_struct2str_preallocated(char* jstr, const int size, void* input, const cjsonx_reflect_t* tbl);

/**
 * Convert struct to cJSON object
 * 
 * @param obj cJSON object
 * @param input Struct address
 * @param tbl Reflection table
 * @return error code
 */
int cjsonx_struct2obj(cJSON* obj, void* input, const cjsonx_reflect_t* tbl);

4.2 使用实例

4.2.1 简单使用

  使用反射的第一步要声明结构体的反射,声明的方式是构建一个不定长反射数组cjsonx_reflect_t device_reflection[]来获取结构体域内存的反射数据,反射数组成员则是前面介绍以双下划线开头的的反射宏函数,声明完成后直接调用正反序列化转换函数完成转换。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "cJSONx.h"

struct device {
   
    int id;
    char name[20];
    float temprature;
    unsigned long tick;
    
    unsigned int ip;
    unsigned int netmask;
    unsigned int gateway;
};

const cjsonx_reflect_t device_reflection[] = {
   
    __cjsonx_int(struct device, id),
    __cjsonx_str(struct device, name),
    __cjsonx_real(struct device, temprature),
    __cjsonx_int(struct device, tick),
    __cjsonx_int(struct device, ip),
    __cjsonx_int(struct device, netmask),
    __cjsonx_int(struct device, gateway),
    
    __cjsonx_end()
};

static void simple_serialize();
static void simple_deserialize();

int main(int argc, char* argv[]) {
   
    simple_serialize();
    simple_deserialize();
}

void simple_serialize() {
   
    struct device d = {
   
        .id = 1,
        .ip = 0x0A01A8C0,
        .gateway = 0x0101A8C0,
        .netmask = 0x00FFFFFF,
        .name = "Hello World",
        .temprature = 36.2F,
        .tick = 123
    };
    char buf[300];
    int ret = cjsonx_struct2str_preallocated(buf, sizeof(buf), &d, device_reflection);
    if (ret == ERR_CJSONX_NONE) {
   
        printf("Serialized JSON string: %s\n", buf
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值