Skip to content

Commit 1e56312

Browse files
committedMar 25, 2025
json: support parsing and serializing of strings with char arrays
Support parsing and serializing of struct fields that are defined as a char array. Use the token JSON_TOK_STRING_BUF to parse and serialize a string for a char array, for example: struct foo { const char *str; char str_buf[30]; }; struct json_obj_descr foo[] = { JSON_OBJ_DESCR_PRIM(struct foo, str, JSON_TOK_STRING), JSON_OBJ_DESCR_PRIM(struct foo, str_buf, JSON_TOK_STRING_BUF), }; The struct 'json_obj_descr' now has an additional union member 'field' to store the size of the struct field, which is used with the token 'JSON_TOK_STRING_BUF' to determine the element size. Fixes: #65200 Signed-off-by: Christoph Winklhofer <cj.winklhofer@gmail.com>
1 parent 9054f10 commit 1e56312

File tree

3 files changed

+382
-120
lines changed

3 files changed

+382
-120
lines changed
 

‎include/zephyr/data/json.h

+7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ enum json_tokens {
3535
JSON_TOK_ARRAY_START = '[',
3636
JSON_TOK_ARRAY_END = ']',
3737
JSON_TOK_STRING = '"',
38+
JSON_TOK_STRING_BUF = 's',
3839
JSON_TOK_COLON = ':',
3940
JSON_TOK_COMMA = ',',
4041
JSON_TOK_NUMBER = '0',
@@ -108,6 +109,9 @@ struct json_obj_descr {
108109
const struct json_obj_descr *element_descr;
109110
size_t n_elements;
110111
} array;
112+
struct {
113+
size_t size;
114+
} field;
111115
};
112116
};
113117

@@ -157,6 +161,9 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
157161
.field_name_len = sizeof(#field_name_) - 1, \
158162
.type = type_, \
159163
.offset = offsetof(struct_, field_name_), \
164+
.field = { \
165+
.size = SIZEOF_FIELD(struct_, field_name_) \
166+
}, \
160167
}
161168

162169
/**

‎lib/utils/json.c

+34-4
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ static int element_token(enum json_tokens token)
307307
case JSON_TOK_OBJECT_START:
308308
case JSON_TOK_ARRAY_START:
309309
case JSON_TOK_STRING:
310+
case JSON_TOK_STRING_BUF:
310311
case JSON_TOK_NUMBER:
311312
case JSON_TOK_INT64:
312313
case JSON_TOK_UINT64:
@@ -419,6 +420,20 @@ static int skip_field(struct json_obj *obj, struct json_obj_key_value *kv)
419420
return 0;
420421
}
421422

423+
static int decode_string_buf(const struct json_token *token, char *str, size_t size)
424+
{
425+
size_t len = token->end - token->start;
426+
427+
if (size <= len) {
428+
return -EINVAL;
429+
}
430+
431+
strncpy(str, token->start, len);
432+
str[len] = '\0';
433+
434+
return 0;
435+
}
436+
422437
static int decode_num(const struct json_token *token, int32_t *num)
423438
{
424439
/* FIXME: strtod() is not available in newlib/minimal libc,
@@ -516,6 +531,10 @@ static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
516531
return true;
517532
}
518533

534+
if (type1 == JSON_TOK_STRING && type2 == JSON_TOK_STRING_BUF) {
535+
return true;
536+
}
537+
519538
if (type1 == JSON_TOK_ARRAY_START && type2 == JSON_TOK_OBJ_ARRAY) {
520539
return true;
521540
}
@@ -595,6 +614,11 @@ static int64_t decode_value(struct json_obj *obj,
595614

596615
return 0;
597616
}
617+
case JSON_TOK_STRING_BUF: {
618+
char *str = field;
619+
620+
return decode_string_buf(value, str, descr->field.size);
621+
}
598622
default:
599623
return -EINVAL;
600624
}
@@ -615,6 +639,8 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
615639
return sizeof(struct json_obj_token);
616640
case JSON_TOK_STRING:
617641
return sizeof(char *);
642+
case JSON_TOK_STRING_BUF:
643+
return descr->field.size;
618644
case JSON_TOK_TRUE:
619645
case JSON_TOK_FALSE:
620646
return sizeof(bool);
@@ -1023,7 +1049,7 @@ static int arr_encode(const struct json_obj_descr *elem_descr,
10231049
return append_bytes("]", 1, data);
10241050
}
10251051

1026-
static int str_encode(const char **str, json_append_bytes_t append_bytes,
1052+
static int str_encode(const char *str, json_append_bytes_t append_bytes,
10271053
void *data)
10281054
{
10291055
int ret;
@@ -1033,7 +1059,7 @@ static int str_encode(const char **str, json_append_bytes_t append_bytes,
10331059
return ret;
10341060
}
10351061

1036-
ret = json_escape_internal(*str, append_bytes, data);
1062+
ret = json_escape_internal(str, append_bytes, data);
10371063
if (!ret) {
10381064
return append_bytes("\"", 1, data);
10391065
}
@@ -1144,7 +1170,12 @@ static int encode(const struct json_obj_descr *descr, const void *val,
11441170
case JSON_TOK_TRUE:
11451171
return bool_encode(ptr, append_bytes, data);
11461172
case JSON_TOK_STRING:
1173+
const char **str = ptr;
1174+
1175+
return str_encode(*str, append_bytes, data);
1176+
case JSON_TOK_STRING_BUF:
11471177
return str_encode(ptr, append_bytes, data);
1178+
11481179
case JSON_TOK_ARRAY_START:
11491180
return arr_encode(descr->array.element_descr, ptr,
11501181
val, append_bytes, data);
@@ -1182,8 +1213,7 @@ int json_obj_encode(const struct json_obj_descr *descr, size_t descr_len,
11821213
}
11831214

11841215
for (i = 0; i < descr_len; i++) {
1185-
ret = str_encode((const char **)&descr[i].field_name,
1186-
append_bytes, data);
1216+
ret = str_encode(descr[i].field_name, append_bytes, data);
11871217
if (ret < 0) {
11881218
return ret;
11891219
}

0 commit comments

Comments
 (0)