Skip to content

Commit 63d33e6

Browse files
cjwinklhoferkartben
authored andcommitted
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_descr[] = { 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 <[email protected]>
1 parent 9157799 commit 63d33e6

File tree

3 files changed

+387
-121
lines changed

3 files changed

+387
-121
lines changed

include/zephyr/data/json.h

Lines changed: 10 additions & 0 deletions
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',
@@ -110,6 +111,9 @@ struct json_obj_descr {
110111
const struct json_obj_descr *element_descr;
111112
size_t n_elements;
112113
} array;
114+
struct {
115+
size_t size;
116+
} field;
113117
};
114118
};
115119

@@ -159,6 +163,9 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
159163
.field_name_len = sizeof(#field_name_) - 1, \
160164
.type = type_, \
161165
.offset = offsetof(struct_, field_name_), \
166+
.field = { \
167+
.size = SIZEOF_FIELD(struct_, field_name_) \
168+
}, \
162169
}
163170

164171
/**
@@ -449,6 +456,9 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len,
449456
.field_name_len = sizeof(json_field_name_) - 1, \
450457
.type = type_, \
451458
.offset = offsetof(struct_, struct_field_name_), \
459+
.field = { \
460+
.size = SIZEOF_FIELD(struct_, struct_field_name_) \
461+
}, \
452462
}
453463

454464
/**

lib/utils/json.c

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ static int element_token(enum json_tokens token)
345345
case JSON_TOK_OBJECT_START:
346346
case JSON_TOK_ARRAY_START:
347347
case JSON_TOK_STRING:
348+
case JSON_TOK_STRING_BUF:
348349
case JSON_TOK_NUMBER:
349350
case JSON_TOK_INT64:
350351
case JSON_TOK_UINT64:
@@ -459,6 +460,21 @@ static int skip_field(struct json_obj *obj, struct json_obj_key_value *kv)
459460
return 0;
460461
}
461462

463+
static int decode_string_buf(const struct json_token *token, char *str, size_t size)
464+
{
465+
size_t len = token->end - token->start;
466+
467+
/* buffer 'str' must be large enough to fit string and null-terminator */
468+
if (size <= len) {
469+
return -EINVAL;
470+
}
471+
472+
memcpy(str, token->start, len);
473+
str[len] = '\0';
474+
475+
return 0;
476+
}
477+
462478
static int decode_num(const struct json_token *token, int32_t *num)
463479
{
464480
/* FIXME: strtod() is not available in newlib/minimal libc,
@@ -626,6 +642,10 @@ static bool equivalent_types(enum json_tokens type1, enum json_tokens type2)
626642
return true;
627643
}
628644

645+
if (type1 == JSON_TOK_STRING && type2 == JSON_TOK_STRING_BUF) {
646+
return true;
647+
}
648+
629649
if (type1 == JSON_TOK_ARRAY_START && type2 == JSON_TOK_OBJ_ARRAY) {
630650
return true;
631651
}
@@ -715,6 +735,11 @@ static int64_t decode_value(struct json_obj *obj,
715735

716736
return 0;
717737
}
738+
case JSON_TOK_STRING_BUF: {
739+
char *str = field;
740+
741+
return decode_string_buf(value, str, descr->field.size);
742+
}
718743
default:
719744
return -EINVAL;
720745
}
@@ -739,6 +764,8 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr)
739764
return sizeof(struct json_obj_token);
740765
case JSON_TOK_STRING:
741766
return sizeof(char *);
767+
case JSON_TOK_STRING_BUF:
768+
return descr->field.size;
742769
case JSON_TOK_TRUE:
743770
case JSON_TOK_FALSE:
744771
return sizeof(bool);
@@ -1147,7 +1174,7 @@ static int arr_encode(const struct json_obj_descr *elem_descr,
11471174
return append_bytes("]", 1, data);
11481175
}
11491176

1150-
static int str_encode(const char **str, json_append_bytes_t append_bytes,
1177+
static int str_encode(const char *str, json_append_bytes_t append_bytes,
11511178
void *data)
11521179
{
11531180
int ret;
@@ -1157,7 +1184,7 @@ static int str_encode(const char **str, json_append_bytes_t append_bytes,
11571184
return ret;
11581185
}
11591186

1160-
ret = json_escape_internal(*str, append_bytes, data);
1187+
ret = json_escape_internal(str, append_bytes, data);
11611188
if (!ret) {
11621189
return append_bytes("\"", 1, data);
11631190
}
@@ -1326,7 +1353,12 @@ static int encode(const struct json_obj_descr *descr, const void *val,
13261353
case JSON_TOK_FALSE:
13271354
case JSON_TOK_TRUE:
13281355
return bool_encode(ptr, append_bytes, data);
1329-
case JSON_TOK_STRING:
1356+
case JSON_TOK_STRING: {
1357+
const char **str = ptr;
1358+
1359+
return str_encode(*str, append_bytes, data);
1360+
}
1361+
case JSON_TOK_STRING_BUF:
13301362
return str_encode(ptr, append_bytes, data);
13311363
case JSON_TOK_ARRAY_START:
13321364
return arr_encode(descr->array.element_descr, ptr,
@@ -1369,8 +1401,7 @@ int json_obj_encode(const struct json_obj_descr *descr, size_t descr_len,
13691401
}
13701402

13711403
for (i = 0; i < descr_len; i++) {
1372-
ret = str_encode((const char **)&descr[i].field_name,
1373-
append_bytes, data);
1404+
ret = str_encode(descr[i].field_name, append_bytes, data);
13741405
if (ret < 0) {
13751406
return ret;
13761407
}

0 commit comments

Comments
 (0)