• 【嵌入式开源学习】__发现了一个很棒的开源项目CSON


    目录

    前言

    思路

    实现

     CSON使用实例

    1. 声明结构体

    2. 定义数据模型 

    3. 使用CSON解析 

    项目地址

    (* ̄︶ ̄)创作不易!期待你们的 点赞、收藏和评论喔。 


    前言

    json是目前最为流行的文本数据传输格式,特别是在网络通信上广泛应用,随着物联网的兴起,在嵌入式设备上,也需要开始使用json进行数据传输,那么,如何快速简洁地用C语言进行json的序列化和反序列化呢

    当前,应用最广泛的C语言json解析库当属 cJSON ,但是,使用cJSON读json进行序列化和反序列化,需要根据key一个一个进行处理,会导致代码冗余,逻辑性不强,哪有没有更好的方法呢

    思路

    在Android平台,一般会使用gson等工具解析json,这些工具将json直接映射成对象,在C语言上使用对象的概念,我们需要借助结构体,然而,最大的问题在于,C语言没有高级语言具有的 反射机制 ,直接从json映射到结构体对象几乎是不可能的

    怎么解决呢,既然C语言没有反射机制,那么我们可以自己定义一套类似于反射的机制,这里我将其称之为结构体 数据模型 ,在数据模型中,我们需要准确地描述结构体的特征,包括结构体各成员的名称,类型,在结构体中的偏移,有了这些,我们可以在解析 json 的时候,将解析得到的数据直接写入到对应的内存里面去,或者是在序列化的时候,直接从对应的内存中读取数据,进行处理

    实现

    CSON正是采用上面说到的思路,使用数据模型对结构体进行描述,然后基于cJSON,根据数据模型进行解析,将解析得到的数据直接写入到对应的内存区域,从而实现从json到结构体对象的映射

    CSON最基本的数据模型定义如下:

    1. typedef struct cson_model
    2. {
    3. CsonType type; /**< 数据类型 */
    4. char *key; /**< 元素键值 */
    5. short offset; /**< 元素偏移 */
    6. } CsonModel;

    通过 type 描述结构体成员的数据类型,key 描述该成员在json中对应的字段,offset 描述该结构体成员在结构体中的偏移,CSON在解析json的时候,根据 type 调用相应的cJSON API并传递 key 作为参数,得到解析出的数据,然后根据 offset 将数据写入到对应的内存空间

    比如说这样一个结构体:

    1. struct project
    2. {
    3. int id;
    4. char *name;
    5. }

    该结构体包含两个成员,对于成员 id ,我们使用数据模型对其进行描述 {.type=CSON_TYPE_CHAR, key="id", offset=0} ,对于结构体的每个成员,都进行数据模型的定义,就可以得到一个完整的结构体数据模型,CSON会根据这个模型,进行解析

    因为是通过直接写内存的方式,所以在写不同类型的量到内存中时,会多次用到强制转型,导致CSON中赋值的代码都类似于 *(int *)((int)obj + model[i].offset) = (int)csonDecodeNumber(json, model[i].key) ;

    当然,上面说到的数据模型,只适用于基本数据类型的数据,对于子结构体,链表,数组等,需要对数据模型的定义进行扩充,有兴趣的朋友可以直接阅读CSON源码

     

     CSON使用实例

    1. 声明结构体

    1. /** 项目结构体 */
    2. struct project
    3. {
    4. int id;
    5. char *name;
    6. };
    7. /** 仓库结构体 */
    8. struct hub
    9. {
    10. int id;
    11. char *user;
    12. struct project *cson;
    13. };

    2. 定义数据模型 

    对每一个需要使用cson的结构体,都需要定义相对应的数据模型

    1. /** 项目结构体数据模型 */
    2. CsonModel projectModel[] =
    3. {
    4. CSON_MODEL_OBJ(struct project),
    5. CSON_MODEL_INT(struct project, id),
    6. CSON_MODEL_STRING(struct project, name),
    7. };
    8. /** 仓库结构体数据模型 */
    9. CsonModel hubModel[] =
    10. {
    11. CSON_MODEL_OBJ(struct hub),
    12. CSON_MODEL_INT(struct hub, id),
    13. CSON_MODEL_STRING(struct hub, user),
    14. CSON_MODEL_STRUCT(struct hub, cson, projectModel, sizeof(projectModel)/sizeof(CsonModel))
    15. };

    3. 使用CSON解析 

    只需要定义好数据模型,就可以使用CSON读json进行序列化和反序列化

    1. void csonDemo(void)
    2. {
    3. char *jsonDemo = "{\"id\": 1, \"user\": \"Letter\", \"cson\": {\"id\": 2, \"name\": \"cson\"}}";
    4. /** 解析json */
    5. struct hub *pHub = csonDecode(jsonDemo, hubModel, sizeof(hubModel)/sizeof(CsonModel));
    6. printf("hub: id: %d, user: %s, project id: %d, project name: %s\r\n",
    7. pHub->id, pHub->user, pHub->cson->id, pHub->cson->name);
    8. /** 序列化对象 */
    9. char *formatJson = csonEncodeFormatted(pHub, hubModel, sizeof(hubModel)/sizeof(CsonModel));
    10. printf("format json: %s\r\n", formatJson);
    11. /** 释放结构体对象 */
    12. csonFree(pHub, hubModel, sizeof(hubModel)/sizeof(CsonModel));
    13. /** 释放序列化生成的json字符串 */
    14. csonFreeJson(formatJson);
    15. }

    运行结果:

    1. hub: id: 1, user: Letter, project id: 2, project name: cson
    2. format json: {
    3. "id": 1,
    4. "user": "Letter",
    5. "cson": {
    6. "id": 2,
    7. "name": "cson"
    8. }
    9. }

    可以看到,无论是解析json,还是序列化结构体到json,在使用CSON的情况下,都只需要一行代码就可以解决,同样的操作,在使用原生cJSON的情况下,你可能需要多次判断,解析元素

    项目地址

    CSON项目已经发布到Github

    https://github.com/NevermindZZT/csonicon-default.png?t=N7T8https://github.com/NevermindZZT/cson

     


    (* ̄︶ ̄)创作不易!期待你们的 点赞收藏评论喔。 

    本文来源网络,免费分享知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除!

  • 相关阅读:
    Python 图形化界面基础篇:添加按钮( Button )到 Tkinter 窗口
    [附源码]java毕业设计学生考试成绩分析系统
    shell/bash脚本命令的基本使用教程
    机器学习——评估和改进学习算法
    vue日历选择
    module内包含第三方aar包,完整打包上传maven的方法
    参与FreeType开源工作的中国人还不少
    arthas的监控java性能
    黑马Java笔记第5讲—方法
    Mybatis深入:数据源实现原理
  • 原文地址:https://blog.csdn.net/weixin_44807874/article/details/134467551