vsfjson -- 不到500行的MCU json库

[复制链接]
806|3
 楼主 | 2018-8-3 07:36 | 显示全部楼层 |阅读模式
本帖最后由 vsfopen 于 2018-8-3 08:44 编辑

坐标:https://gitee.com/versaloon/vsf_open/blob/master/vsf/component/tool/json

极简方式实现,不使用中间结构,不是用动态分配,不使用递归,不使用全局变量。
RAM只使用堆栈,做大堆栈使用的函数是vsfjson_set_number,使用68字节堆栈(4字节返回值和64字节字符串缓冲)。
支持json解析和json生成
json生成时候,数据保存接口由用户定义
资源按需分配,比如解析json的时候,如果没有调用vsfjson_get_number,编译器就可以优化去掉浮点数的部分。

目前代码vsfjson.c为391字节,不过刚刚写好,兼容性还没做太多测试,并且以后会增加一些其他API。

demo:
  1. static int usrapp_json_write_str(void *param, char *ch, int len)
  2. {
  3.         struct vsf_transaction_buffer_t *buf = (struct vsf_transaction_buffer_t *)param;
  4.         if (buf->buffer.buffer != NULL)
  5.         {
  6.                 if ((buf->buffer.size - buf->position) >= len)
  7.                 {
  8.                         memcpy(&buf->buffer.buffer[buf->position], ch, len);
  9.                         buf->position += len;
  10.                         return 0;
  11.                 }
  12.         }
  13.         return -1;
  14. }

  15. void usrapp_json_test(void)
  16. {
  17.         const char *json = "{\"obj\":{\"arr\":[0.01, 1.01],\"str\":\"abcd\"},\"uuid\":\"012376545672184\"}";
  18.         double double_value;
  19.         char buff[128];
  20.         int len;

  21.         char *result = vsfjson_get(json, "/obj/str");
  22.         if (result != NULL)
  23.         {
  24.                 len = vsfjson_get_string(result, NULL, 0);
  25.                 if (len < sizeof(buff))
  26.                 {
  27.                         vsfjson_get_string(result, buff, len);
  28.                 }
  29.         }
  30.         result = vsfjson_get(json, "obj");
  31.         if (result != NULL)
  32.         {
  33.                 result = vsfjson_get(result, "str");
  34.                 if (result != NULL)
  35.                 {
  36.                         len = vsfjson_get_string(result, NULL, 0);
  37.                         if (len < sizeof(buff))
  38.                         {
  39.                                 vsfjson_get_string(result, buff, len);
  40.                         }
  41.                 }
  42.         }
  43.         result = vsfjson_get(json, "obj/arr/0");
  44.         if (result != NULL)
  45.         {
  46.                 len = vsfjson_get_number(result, &double_value);
  47.         }

  48. /*        "{
  49.                 "key0":1.0,
  50.                 "key1":true,
  51.                 "key2":["123", 4.56],
  52.                 "key3":null
  53.         }
  54. */
  55.         struct vsfjson_constructor_t c;
  56.         struct vsf_transaction_buffer_t buf = { NULL, 0 };

  57.         do
  58.         {
  59.                 if (buf.buffer.size)
  60.                 {
  61.                         if (buf.buffer.size < sizeof(buff))
  62.                         {
  63.                                 buf.buffer.buffer = (uint8_t *)buff;
  64.                                 buf.position = 0;
  65.                                 vsfjson_constructor_init(&c, &buf, usrapp_json_write_str);
  66.                         }
  67.                         else
  68.                                 break;
  69.                 }
  70.                 else
  71.                 {
  72.                         vsfjson_constructor_init(&c, NULL, NULL);
  73.                 }

  74.                 vsfjson_set_object(&c, NULL,
  75.                 {
  76.                         vsfjson_set_number(&c, "key0", 1.0);
  77.                         vsfjson_set_boolean(&c, "key1", true);
  78.                         vsfjson_set_array(&c, "key2",
  79.                         {
  80.                                 vsfjson_set_string(&c, NULL, "123");
  81.                                 vsfjson_set_number(&c, NULL, 4.67);
  82.                         });
  83.                         vsfjson_set_null(&c, "key3");
  84.                 });
  85.                 if (!c.write_str)
  86.                         buf.buffer.size = c.len + 1;
  87.                 else
  88.                         c.write_str(c.param, "\0", 1);
  89.         } while (!buf.buffer.buffer);
  90. }
复制代码


API:
1. char *vsfjson_get(const char *json, const char *key);
从json字符串后,或者指定的key的值,key可以用路径的方式表示,比如"/obj/arr/2"(obj需要是object,arr需要是array)。
2. enum vsfjson_type_t vsfjson_enumerate_start(struct vsfjson_enumerator_t *e, const char *json);
vsfjson_enumerate_start用于枚举指定的json,只对array和object有效。struct vsfjson_enumerator_t为枚举器。
3. char *vsfjson_enumerate_next(struct vsfjson_enumerator_t *e);
枚举array或者object的时候,用来得到下一个值。
4. enum vsfjson_type_t vsfjson_get_type(const char *json);
得到json的类型,比如object、array、number、string等等。
5. int vsfjson_get_string(const char *json, char *result, int len);
对于string类型的json,读取字符串的值,并且返回长度。如果result为NULL,可以返回保存字符串需要的长度。
6. int vsfjson_get_number(const char *json, double *result);
对于number类型的json,读取double类型的值。
7. int vsfjson_get_boolean(const char *json, bool *result);
对于boolean类型的json,读取bool类型的值。
8. void vsfjson_constructor_init(struct vsfjson_constructor_t *c, void *param, int (*write_str)(void *, char *, int));
初始化struct vsfjson_constructor_t构造器,并且指定写数据的用户回调,如果用户回调设置为NULL的话,则用来计算生成的json数据长度。
9. vsfjson_set_object(c, key, member);
json构造器中,加入指定key的object,member要使用闭包的方式。比如:
  1. vsfjson_set_object(&c, "KEY0",
  2. {
  3.   vsfjson_set_boolean(&c, "enabled", true);
  4. });
复制代码
如果key参数为NULL的话,则生成不带名字的object(一般其他的成员,都写在一个不带名字的object内)。
10. vsfjson_set_array(c, key, member);
类似vsfjson_set_object,不过这里member里的成员,都必须不带key。
11. int vsfjson_set_string(struct vsfjson_constructor_t *c, char *key, char *value);
json构造器中,加入string。生成"key":"value"
12. int vsfjson_set_number(struct vsfjson_constructor_t *c, char *key, double value);
json构造器中,加入number。生成"key":double(value)
13. int vsfjson_set_boolean(struct vsfjson_constructor_t *c, char *key, bool value);
json构造器中,加入boolean。生成"key":true/false
14. int vsfjson_set_null(struct vsfjson_constructor_t *c, char *key);
json构造器中,加入null。生成"key":null


使用特权

评论回复
| 2018-8-9 22:11 | 显示全部楼层
json已经把几年前还到处见的xml打的满地找牙了。

使用特权

评论回复
 楼主 | 2018-8-9 22:17 | 显示全部楼层
linqing171 发表于 2018-8-9 22:11
json已经把几年前还到处见的xml打的满地找牙了。

是啊,我们还有小资源占用的xml库,不过现在确实不想用xml的,都懒得整理代码发布了。

使用特权

评论回复
| 2019-6-18 20:09 | 显示全部楼层
在线等在线等

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表