vsfjson -- 不到500行的MCU json库
参考:https://bbs.21ic.com/icview-2537088-1-1.html
源码:https://gitee.com/cksweb/vsf_open/blob/master/vsf/component/tool/json/vsfjson.c
注意点
1.注意加入anon_unions选项,否则联合体报错
2.因为构造json需要一个buf和存储方法,这里要自己选定一个buf,所以这里加一个静态buf和使用memcpy
3.构造json时,buf指针是不会偏移的,注意自己处理下标的增加
4.构造完成后,使用后记得将buf清空,下标归0
5.使用构造前,必须调用init ,将buf和存储方法导入到里面
我修改过的源码贴出来(STM32F030平台)
c文件
#include "json.h" #include "config.h" struct vsfjson_constructor_t json_c; static uint16_t s_json_len = 0; char json_s_buf[JSON_S_LEN];//注意JSON最大长度 static bool vsfjson_token_match(const char *json, const char *value) { int n = strlen(value); return !strncmp(json, value, n) && !isalnum(json[n]); } enum vsfjson_type_t vsfjson_get_type(const char *json) { enum vsfjson_type_t type = VSFJSON_TYPE_INVALID; char ch = *json; if (ch == '{') type = VSFJSON_TYPE_OBJECT; else if (ch == '[') type = VSFJSON_TYPE_ARRAY; else if (ch == '"') type = VSFJSON_TYPE_STRING; else if ((ch >= '0') && (ch <= '9')) type = VSFJSON_TYPE_NUMBER; else if (vsfjson_token_match(json, "true") || vsfjson_token_match(json, "false")) type = VSFJSON_TYPE_BOOLEAN; else if (vsfjson_token_match(json, "null")) type = VSFJSON_TYPE_NULL; return type; } static char *vsfjson_skip_space(const char *json) { while ((*json != '\0') && isspace(*json)) json++; return *json == '\0' ? NULL : (char *)json; } enum vsfjson_type_t vsfjson_enumerate_start( struct vsfjson_enumerator_t *e, const char *json) { enum vsfjson_type_t type = vsfjson_get_type(json); if ((type != VSFJSON_TYPE_OBJECT) && (type != VSFJSON_TYPE_ARRAY)) type = VSFJSON_TYPE_INVALID; else { e->ptr = (char *)json; e->type = type; e->first = true; e->ptr = vsfjson_skip_space(++e->ptr); if (!e->ptr) type = VSFJSON_TYPE_INVALID; } return type; } char *vsfjson_enumerate_next(struct vsfjson_enumerator_t *e) { char *cur = e->ptr; bool str = false; int brace_level = 0, square_level = 0; if (e->first) { e->first = false; if (*cur == ',') return NULL; goto exit; } else { while (*cur != '\0') { switch (*cur) { case '\"': str = !str; break; case '\\': if (!str) return NULL; cur++; break; case '{': if (!str) brace_level++; break; case '[': if (!str) square_level++; break; case ',': if (!str && !brace_level && !square_level) { cur = vsfjson_skip_space(++cur); goto exit; } break; case '}': if (!str) { brace_level--; if (brace_level < 0) return NULL; goto check; } break; case ']': if (!str) { square_level--; if (square_level < 0) return NULL; check: if (!brace_level && !square_level) { cur = vsfjson_skip_space(++cur); if (*cur == ',') { cur = vsfjson_skip_space(++cur); goto exit; } else { return NULL; } } } break; } cur++; } exit: if ((*cur == '}') || (*cur == ']')) return NULL; } e->ptr = cur; return cur; } static bool vsfjson_isdiv(char ch) { return (ch == '/') || (ch == '\\'); } int vsfjson_num_of_entry(const char *json) { struct vsfjson_enumerator_t e; int num_of_entry = 0; if (vsfjson_enumerate_start(&e, json) != VSFJSON_TYPE_INVALID) while (vsfjson_enumerate_next(&e) != NULL) num_of_entry++; return num_of_entry; } char *vsfjson_get(const char *json, const char *key) { struct vsfjson_enumerator_t e; unsigned long idx, curidx; char *cur; if (vsfjson_isdiv(*key)) key++; while (*key != '\0') { if (VSFJSON_TYPE_INVALID == vsfjson_enumerate_start(&e, json)) return NULL; if (e.type == VSFJSON_TYPE_ARRAY) { idx = strtoul(key, (char **)&key, 0); curidx = 0; } else { for (idx = 0; key[idx] && !vsfjson_isdiv(key[idx]); idx++); } while (1) { cur = vsfjson_enumerate_next(&e); if (!cur) return NULL; if (e.type == VSFJSON_TYPE_ARRAY) { if (curidx++ == idx) { json = cur; break; } } else { if (*cur++ != '\"') return NULL; if (!strncmp(key, cur, idx) && (cur[idx] == '\"')) { key += idx; if (*key) key++; cur += idx + 1; cur = vsfjson_skip_space(cur); if (*cur++ != ':') return NULL; json = vsfjson_skip_space(cur); break; } } } } return (char *)json; } int vsfjson_get_string(const char *json, char *result, int len) { char ch; int curlen = 0; if (*json++ != '"') return -1; do { ch = *json++; if (ch == '\\') { ch = *json++; if (result && (curlen >= len)) return VSFERR_NOT_ENOUGH_RESOURCES; switch (ch) { case '"': if (result) result[curlen] = '\"'; curlen++;break; case '\\': if (result) result[curlen] = '\\'; curlen++;break; case '/': if (result) result[curlen] = '/'; curlen++;break; case 'b': if (result) result[curlen] = '\b'; curlen++;break; case 'f': if (result) result[curlen] = '\f'; curlen++;break; case 'n': if (result) result[curlen] = '\n'; curlen++;break; case 'r': if (result) result[curlen] = '\r'; curlen++;break; case 't': if (result) result[curlen] = '\t'; curlen++;break; case 'u': // TODO: break; default: return -1; } } else if (ch != '\"') { if (result && (curlen >= len)) return VSFERR_NOT_ENOUGH_RESOURCES; if (result) result[curlen] = ch; curlen++; } } while (ch != '\"'); if (result && (curlen >= len)) return VSFERR_NOT_ENOUGH_RESOURCES; if (result) result[curlen] = '\0'; return ++curlen; } int vsfjson_get_number(const char *json, double *result) { double value = strtod(json, NULL); if (result) *result = value; return sizeof(*result); } int vsfjson_get_boolean(const char *json, bool *result) { bool value; if (vsfjson_token_match(json, "true")) value = true; else if (vsfjson_token_match(json, "false")) value = false; else return -1; if (result) *result = value; return sizeof(*result); } // constructor void vsfjson_constructor_init(struct vsfjson_constructor_t *c, void *param, int (*write_str)(void *, char *, int)) { c->write_str = write_str; if (write_str != NULL) c->param = param; else c->len = 0; c->first = true; c->result = true; } int vsfjson_write_str(struct vsfjson_constructor_t *c, char *buf, int len) { if (c->write_str != NULL) { int ret = c->write_str(c->param, buf, len); if (ret < 0) c->result = false; return ret; } else { c->len += len; return 0; } } static int vsfjson_set_token(struct vsfjson_constructor_t *c, char *token) { int n = strlen(token); return vsfjson_write_str(c, token, n); } int vsfjson_set_key(struct vsfjson_constructor_t *c, char *key) { int ret; if (c->first) c->first = false; else { ret = vsfjson_write_str(c, ",", 1); if (ret < 0) return ret; } if (key != NULL) { ret = vsfjson_write_str(c, "\"", 1); if (ret < 0) return ret; ret = vsfjson_set_token(c, key); if (ret < 0) return ret; ret = vsfjson_write_str(c, "\"", 1); if (ret < 0) return ret; ret = vsfjson_write_str(c, ":", 1); if (ret < 0) return ret; } return 0; } int vsfjson_set_string(struct vsfjson_constructor_t *c, char *key, char *value) { int ret; char ch, buf[2]; ret = vsfjson_set_key(c, key); if (ret < 0) return ret; ret = vsfjson_write_str(c, "\"", 1); if (ret < 0) return ret; do { ch = *value++; switch (ch) { case '\0': break; case '\"': buf[1] = '"'; goto set_esc; case '\\': buf[1] = '\\'; goto set_esc; case '/': buf[1] = '/'; goto set_esc; case '\b': buf[1] = 'b'; goto set_esc; case '\f': buf[1] = 'b'; goto set_esc; case '\n': buf[1] = 'n'; goto set_esc; case '\r': buf[1] = 'r'; goto set_esc; case '\t': buf[1] = 't'; set_esc: buf[0] = '\\'; ret = vsfjson_write_str(c, buf, 2); if (ret < 0) return ret; break; default: buf[0] = ch; ret = vsfjson_write_str(c, buf, 1); if (ret < 0) return ret; break; } } while (ch != '\0'); ret = vsfjson_write_str(c, "\"", 1); return (ret < 0) ? ret : 0; } int vsfjson_set_number(struct vsfjson_constructor_t *c, char *key, double value) { int ret; char buf[64]; ret = vsfjson_set_key(c, key); if (ret < 0) return ret; ret = snprintf(buf, sizeof(buf), "%f", value); ret = vsfjson_write_str(c, buf, ret); return (ret < 0) ? ret : 0; } int vsfjson_set_boolean(struct vsfjson_constructor_t *c, char *key, bool value) { if (vsfjson_set_key(c, key) < 0) return -1; return vsfjson_set_token(c, value ? "true" : "false"); } int vsfjson_set_null(struct vsfjson_constructor_t *c, char *key) { if (vsfjson_set_key(c, key) < 0) return -1; return vsfjson_set_token(c, "null"); } static int usrapp_json_write_str(void *param, char *ch, int len) { #if 0 struct vsf_transaction_buffer_t *buf = (struct vsf_transaction_buffer_t *)param; if (buf->buffer.buffer != NULL) { if ((buf->buffer.size - buf->position) >= len) { memcpy(&buf->buffer.buffer[buf->position], ch, len); buf->position += len; return 0; } } return -1; #else if(s_json_len < JSON_S_LEN) { memcpy( (char *)param+s_json_len, ch, len); s_json_len += len; return 0; } return -1; #endif } void json_user_flush() { s_json_len = 0; memset(json_s_buf,0,JSON_S_LEN); } void json_user_init() { vsfjson_constructor_init(&json_c, json_s_buf, usrapp_json_write_str); json_user_flush(); } void json_user_test() { const char *json = "{\"obj\":{\"arr\":[0.01,\"1000\"],\"str\":\"abcd\"},\"uuid\":\"012376545672184\"}"; double double_value; char buff[128]; int len; char *result = vsfjson_get(json, "uuid"); if (result != NULL) { len = vsfjson_get_string(result, NULL, 0); if (len < sizeof(buff)) { vsfjson_get_string(result, buff, len); printf("len = %d data=%s\r\n",len,buff); } } result = vsfjson_get(json, "obj"); if (result != NULL) { result = vsfjson_get(result, "str"); if (result != NULL) { len = vsfjson_get_string(result, NULL, 0); if (len < sizeof(buff)) { vsfjson_get_string(result, buff, len); printf("len = %d data=%s\r\n",len,buff); } } } result = vsfjson_get(json, "obj/arr/0"); if (result != NULL) { len = vsfjson_get_number(result, &double_value); printf("len = %d data=%f\r\n",len,double_value); } result = vsfjson_get(json, "obj/arr/1"); if (result != NULL) { // len = vsfjson_get_number(result, &double_value); // DBG("len = %d data=%f\r\n",len,double_value); len = vsfjson_get_string(result, NULL, 0); if (len < sizeof(buff)) { vsfjson_get_string(result, buff, len); printf("len = %d data=%s\r\n",len,buff); } } json_user_init(); vsfjson_set_object(&json_c, NULL, { vsfjson_set_number(&json_c, "key0", 1.0); vsfjson_set_boolean(&json_c, "key1", true); vsfjson_set_array(&json_c, "key2", { vsfjson_set_string(&json_c, NULL, "123"); vsfjson_set_number(&json_c, NULL, 4.67); }); vsfjson_set_null(&json_c, "key3"); }); printf("s_buf = %s\r\n",json_s_buf); json_user_flush(); vsfjson_set_object(&json_c, NULL, { vsfjson_set_number(&json_c, "测试1", 1.0); vsfjson_set_boolean(&json_c, "测试2", true); vsfjson_set_array(&json_c, "key2", { vsfjson_set_string(&json_c, NULL, "123"); vsfjson_set_number(&json_c, NULL, 1000); vsfjson_set_number(&json_c, NULL, 4.67); vsfjson_set_number(&json_c, NULL, 4.67); vsfjson_set_string(&json_c, NULL, "cba"); }); vsfjson_set_null(&json_c, "key3"); }); printf("s_buf = %s\r\n",json_s_buf); json_user_flush(); } ///测试 #if 0 static uint8_t s_json_len = 0; static int usrapp_json_write_str(void *param, char *ch, int len) { #if 0 struct vsf_transaction_buffer_t *buf = (struct vsf_transaction_buffer_t *)param; if (buf->buffer.buffer != NULL) { if ((buf->buffer.size - buf->position) >= len) { memcpy(&buf->buffer.buffer[buf->position], ch, len); buf->position += len; return 0; } } return -1; #else memcpy( (char *)param+s_json_len, ch, len); s_json_len += len; return 0; #endif } char s_buf[128]; void usrapp_json_test(void) { const char *json = "{\"obj\":{\"arr\":[0.01,\"1000\"],\"str\":\"abcd\"},\"uuid\":\"012376545672184\"}"; double double_value; char buff[128]; int len; struct vsfjson_constructor_t c; char *result = vsfjson_get(json, "uuid"); if (result != NULL) { len = vsfjson_get_string(result, NULL, 0); if (len < sizeof(buff)) { vsfjson_get_string(result, buff, len); DBG("len = %d data=%s\r\n",len,buff); } } result = vsfjson_get(json, "obj"); if (result != NULL) { result = vsfjson_get(result, "str"); if (result != NULL) { len = vsfjson_get_string(result, NULL, 0); if (len < sizeof(buff)) { vsfjson_get_string(result, buff, len); DBG("len = %d data=%s\r\n",len,buff); } } } result = vsfjson_get(json, "obj/arr/0"); if (result != NULL) { len = vsfjson_get_number(result, &double_value); DBG("len = %d data=%f\r\n",len,double_value); } result = vsfjson_get(json, "obj/arr/1"); if (result != NULL) { // len = vsfjson_get_number(result, &double_value); // DBG("len = %d data=%f\r\n",len,double_value); len = vsfjson_get_string(result, NULL, 0); if (len < sizeof(buff)) { vsfjson_get_string(result, buff, len); DBG("len = %d data=%s\r\n",len,buff); } } /* "{ "key0":1.0, "key1":true, "key2":["123", 4.56], "key3":null } */ vsfjson_constructor_init(&c, s_buf, usrapp_json_write_str); vsfjson_set_object(&c, NULL, { vsfjson_set_number(&c, "key0", 1.0); vsfjson_set_boolean(&c, "key1", true); vsfjson_set_array(&c, "key2", { vsfjson_set_string(&c, NULL, "123"); vsfjson_set_number(&c, NULL, 4.67); }); vsfjson_set_null(&c, "key3"); }); s_json_len = 0; printf("s_buf = %s\r\n",s_buf); #if 0 struct vsfjson_constructor_t c; struct vsf_transaction_buffer_t buf = { NULL, 0 }; do { if (buf.buffer.size) { if (buf.buffer.size < sizeof(buff)) { buf.buffer.buffer = (uint8_t *)buff; buf.position = 0; vsfjson_constructor_init(&c, &buf, usrapp_json_write_str); } else break; } else { vsfjson_constructor_init(&c, NULL, NULL); } vsfjson_set_object(&c, NULL, { vsfjson_set_number(&c, "key0", 1.0); vsfjson_set_boolean(&c, "key1", true); vsfjson_set_array(&c, "key2", { vsfjson_set_string(&c, NULL, "123"); vsfjson_set_number(&c, NULL, 4.67); }); vsfjson_set_null(&c, "key3"); }); if (!c.write_str) buf.buffer.size = c.len + 1; else c.write_str(c.param, "\0", 1); } while (!buf.buffer.buffer); #endif } #endif
h文件
#ifndef __VSFJSON_H_INCLUDED__ #define __VSFJSON_H_INCLUDED__ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <stdint.h> #include <ctype.h> #pragma anon_unions #define JSON_S_LEN 512 extern struct vsfjson_constructor_t json_c; extern char json_s_buf[JSON_S_LEN]; static uint16_t s_json_len ; #define VSFERR_NOT_ENOUGH_RESOURCES -1 enum vsfjson_type_t { VSFJSON_TYPE_INVALID, VSFJSON_TYPE_OBJECT, VSFJSON_TYPE_ARRAY, VSFJSON_TYPE_STRING, VSFJSON_TYPE_NUMBER, VSFJSON_TYPE_BOOLEAN, VSFJSON_TYPE_NULL, }; struct vsfjson_enumerator_t { char *ptr; enum vsfjson_type_t type; bool first; }; struct vsfjson_constructor_t { union { void *param; uint32_t len; }; int (*write_str)(void *, char *, int); bool first; bool result; }; enum vsfjson_type_t vsfjson_enumerate_start(struct vsfjson_enumerator_t *e, const char *json); char *vsfjson_enumerate_next(struct vsfjson_enumerator_t *e); char *vsfjson_get(const char *json, const char *key); int vsfjson_num_of_entry(const char *json); enum vsfjson_type_t vsfjson_get_type(const char *json); int vsfjson_get_string(const char *json, char *result, int len); int vsfjson_get_number(const char *json, double *result); int vsfjson_get_boolean(const char *json, bool *result); void vsfjson_constructor_init(struct vsfjson_constructor_t *c, void *param, int (*write_str)(void *, char *, int)); int vsfjson_write_str(struct vsfjson_constructor_t *c, char *buf, int len); int vsfjson_set_key(struct vsfjson_constructor_t *c, char *key); #define vsfjson_set_object(c, key, member) \ do {\ int len = vsfjson_set_key((c), (key));\ if (len < 0) break;\ (c)->first = true;\ len = vsfjson_write_str((c), "{", 1);\ if (len < 0) break;\ member\ len = vsfjson_write_str((c), "}", 1);\ if (len < 0) break;\ } while (0) #define vsfjson_set_array(c, key, member) \ do {\ int len = vsfjson_set_key((c), (key));\ if (len < 0) break;\ (c)->first = true;\ len = vsfjson_write_str((c), "[", 1);\ if (len < 0) break;\ member\ len = vsfjson_write_str((c), "]", 1);\ if (len < 0) break;\ } while (0) int vsfjson_set_string(struct vsfjson_constructor_t *c, char *key, char *value); int vsfjson_set_number(struct vsfjson_constructor_t *c, char *key, double value); int vsfjson_set_boolean(struct vsfjson_constructor_t *c, char *key, bool value); int vsfjson_set_null(struct vsfjson_constructor_t *c, char *key); void json_user_init(void); void json_user_flush(void); void json_user_test(void); #endif // __VSFJSON_H_INCLUDED__

浙公网安备 33010602011771号