Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

json: support parsing and serializing of char arrays and integers (int8_t, uint8_t, etc.) #87580

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

cjwinklhofer
Copy link

@cjwinklhofer cjwinklhofer commented Mar 24, 2025

Support parsing and serializing of char arrays and integers

By extending the struct 'json_obj_descr' with an additional union member 'field' that stores the size of the struct field it is possible to serialize and parse char arrays, integers with different width and also enum types. Added three new tokens:

  • JSON_TOK_STRING_BUF: for char arrays
  • JSON_TOK_INT: "generic" signed integer types (int8_t, int16_t, int32_t, int64_t)
  • JSON_TOK_UINT: "generic" unsigned integer types (uint8_t, uint16_t, uint32_t, uint64_t)

Strings with char arrays

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),
};

Integers of different width

Use the token JSON_TOK_INT or JSON_TOK_UINT to parse and serialize integers of different types - for example:

struct foo {
  int64_t i64;
  uint32_t u32;
  int16_t i16;
  uint8_t u8;
};

struct json_obj_descr foo[] = {
  JSON_OBJ_DESCR_PRIM(struct foo, i64, JSON_TOK_INT),
  JSON_OBJ_DESCR_PRIM(struct foo, u32, JSON_TOK_UINT),
  JSON_OBJ_DESCR_PRIM(struct foo, i16, JSON_TOK_INT),
  JSON_OBJ_DESCR_PRIM(struct foo, u8, JSON_TOK_UINT),
};

Parsing and serializing enums

enum unsigned_enum { UA=0, UB=1, UC=2 };
enum signed_enum { SA=-1, SB=0, SC=1 };

struct foo {
  enum unsigned_enum u;
  enum signed_enum s;
};

struct json_obj_descr foo[] = {
  JSON_OBJ_DESCR_PRIM(struct foo, u, JSON_TOK_UINT),
  JSON_OBJ_DESCR_PRIM(struct foo, s, JSON_TOK_INT),
};

Fixes: #65200

The calculation of the object size may be incorrect when the size of
a field is smaller than the struct alignment. When such a struct is
used in an array field, the decoded object contains wrong values.

The alignment influences the object size. For example the following
struct has a calculated object size of 8 bytes, however due to
alignment the real size of the struct is 12 bytes:

struct test_bool {
  bool b1; /* offset 0, size 1 */
           /* 3-byte padding */
  int i1;  /* offset 4, size 4 */
  bool b2; /* offset 8, size 1 */
           /* 3-byte padding */
};

This commit changes the object size calculation and computes the size
with the offset and size of the last field in the struct (rounded up
by the struct alignment).

Fixes: zephyrproject-rtos#85121
Signed-off-by: Christoph Winklhofer <cj.winklhofer@gmail.com>
@cjwinklhofer cjwinklhofer force-pushed the fix_json_string_array branch 2 times, most recently from 0cf3258 to ce7bf51 Compare March 25, 2025 15:58
@cjwinklhofer cjwinklhofer marked this pull request as draft March 25, 2025 17:09
@cjwinklhofer cjwinklhofer force-pushed the fix_json_string_array branch 3 times, most recently from 1e56312 to 651d140 Compare March 26, 2025 06:14
@cjwinklhofer cjwinklhofer changed the title json: support parsing and serializing of strings with char arrays json: support parsing and serializing of char arrays and integers (int8_t, uint8_t, etc.) Mar 27, 2025
@cjwinklhofer cjwinklhofer marked this pull request as ready for review March 27, 2025 17:19
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: zephyrproject-rtos#65200
Signed-off-by: Christoph Winklhofer <cj.winklhofer@gmail.com>
@cjwinklhofer cjwinklhofer force-pushed the fix_json_string_array branch from 0bbb3ad to 35b26d3 Compare March 28, 2025 06:07
Add support for parsing and serializing of following integer types:
'int8_t', 'uint8_t', 'int16_t', 'uint16_t' and 'uint32_t'.

The generic integer token JSON_TOK_INT and JSON_TOK_UINT, in combination
with the field size (set by JSON_OBJ_DESCR_PRIM) allows to parse different
integer types, for example:

struct foo {
  int64_t i64;
  uint32_t u32;
  int16_t i16;
  uint8_t u8;
};

struct json_obj_descr foo[] = {
  JSON_OBJ_DESCR_PRIM(struct foo, i64, JSON_TOK_INT),
  JSON_OBJ_DESCR_PRIM(struct foo, u32, JSON_TOK_UINT),
  JSON_OBJ_DESCR_PRIM(struct foo, i16, JSON_TOK_INT),
  JSON_OBJ_DESCR_PRIM(struct foo, u8, JSON_TOK_UINT),
};

These tokens also support parsing and serializing enums:

enum unsigned_enum { UA=0, UB=1, UC=2 };
enum signed_enum { SA=-1, SB=0, SC=1 };

struct foo {
  enum unsigned_enum u;
  enum signed_enum s;
};

struct json_obj_descr foo[] = {
  JSON_OBJ_DESCR_PRIM(struct foo, u, JSON_TOK_UINT),
  JSON_OBJ_DESCR_PRIM(struct foo, s, JSON_TOK_INT),
};

Signed-off-by: Christoph Winklhofer <cj.winklhofer@gmail.com>
@cjwinklhofer cjwinklhofer force-pushed the fix_json_string_array branch from 35b26d3 to 9553f49 Compare March 28, 2025 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Json encode char array field
3 participants