From c6bc548b737cc159821e9a1a88e30c5cbf05f002 Mon Sep 17 00:00:00 2001 From: Markus Fuchs Date: Fri, 29 Oct 2021 17:32:37 +0200 Subject: [PATCH] json: Add top-level array decoding support The library supports encoding JSON objects and arrays as well as parsing JSON objects. Introduce a new function json_arr_parse() adding support for parsing top-level JSON arrays. Signed-off-by: Markus Fuchs --- include/data/json.h | 37 ++++++++++++++++++++++++++++++++++++- lib/os/json.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/include/data/json.h b/include/data/json.h index a9f2817c39b..c12c89913c1 100644 --- a/include/data/json.h +++ b/include/data/json.h @@ -528,7 +528,7 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, } /** - * @brief Parses the JSON-encoded object pointer to by @a json, with + * @brief Parses the JSON-encoded object pointed to by @a json, with * size @a len, according to the descriptor pointed to by @a descr. * Values are stored in a struct pointed to by @a val. Set up the * descriptor like this: @@ -561,6 +561,41 @@ int json_obj_parse(char *json, size_t len, const struct json_obj_descr *descr, size_t descr_len, void *val); +/** + * @brief Parses the JSON-encoded array pointed to by @a json, with + * size @a len, according to the descriptor pointed to by @a descr. + * Values are stored in a struct pointed to by @a val. Set up the + * descriptor like this: + * + * struct s { int foo; char *bar; } + * struct json_obj_descr descr[] = { + * JSON_OBJ_DESCR_PRIM(struct s, foo, JSON_TOK_NUMBER), + * JSON_OBJ_DESCR_PRIM(struct s, bar, JSON_TOK_STRING), + * }; + * struct a { struct s baz[10]; size_t count; } + * struct json_obj_descr array[] = { + * JSON_OBJ_DESCR_OBJ_ARRAY(struct a, baz, 10, count, + * descr, ARRAY_SIZE(descr)), + * }; + * + * Since this parser is designed for machine-to-machine communications, some + * liberties were taken to simplify the design: + * (1) strings are not unescaped (but only valid escape sequences are + * accepted); + * (2) no UTF-8 validation is performed; and + * (3) only integer numbers are supported (no strtod() in the minimal libc). + * + * @param json Pointer to JSON-encoded array to be parsed + * @param len Length of JSON-encoded array + * @param descr Pointer to the descriptor array + * @param val Pointer to the struct to hold the decoded values + * + * @return 0 if array has been successfully parsed. A negative value + * indicates an error (as defined on errno.h). + */ +int json_arr_parse(char *json, size_t len, + const struct json_obj_descr *descr, void *val); + /** * @brief Escapes the string so it can be used to encode JSON objects * diff --git a/lib/os/json.c b/lib/os/json.c index bb2c9629c5e..7dd4f7a32ce 100644 --- a/lib/os/json.c +++ b/lib/os/json.c @@ -302,6 +302,23 @@ static int obj_init(struct json_obj *json, char *data, size_t len) return 0; } +static int arr_init(struct json_obj *json, char *data, size_t len) +{ + struct token token; + + lexer_init(&json->lexer, data, len); + + if (!lexer_next(&json->lexer, &token)) { + return -EINVAL; + } + + if (token.type != JSON_TOK_ARRAY_START) { + return -EINVAL; + } + + return 0; +} + static int element_token(enum json_tokens token) { switch (token) { @@ -607,6 +624,23 @@ int json_obj_parse(char *payload, size_t len, return obj_parse(&obj, descr, descr_len, val); } +int json_arr_parse(char *payload, size_t len, + const struct json_obj_descr *descr, void *val) +{ + struct json_obj arr; + int ret; + + ret = arr_init(&arr, payload, len); + if (ret < 0) { + return ret; + } + + void *ptr = (char *)val + descr->offset; + + return arr_parse(&arr, descr->array.element_descr, + descr->array.n_elements, ptr, val); +} + static char escape_as(char chr) { switch (chr) {