Skip to content

Commit 6c37aa9

Browse files
SanjayyyVcfriedt
authored andcommitted
include: zephyr: data: add mixed array type support for json
Introduced a mixed array type for JSON using the struct json_mixed_arr_descr. Added helper macros to define elements of the descriptor array. Signed-off-by: Sanjay Vallimanalan <[email protected]>
1 parent ff9e29b commit 6c37aa9

File tree

1 file changed

+227
-0
lines changed

1 file changed

+227
-0
lines changed

include/zephyr/data/json.h

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ enum json_tokens {
5151
JSON_TOK_UINT = 'u',
5252
JSON_TOK_TRUE = 't',
5353
JSON_TOK_FALSE = 'f',
54+
JSON_TOK_MIXED_ARRAY = 'm',
5455
JSON_TOK_NULL = 'n',
5556
JSON_TOK_ERROR = '!',
5657
JSON_TOK_EOF = '\0',
@@ -811,6 +812,232 @@ int json_obj_encode(const struct json_obj_descr *descr, size_t descr_len,
811812
int json_arr_encode(const struct json_obj_descr *descr, const void *val,
812813
json_append_bytes_t append_bytes, void *data);
813814

815+
/**
816+
* @brief Descriptor for a mixed-type JSON array.
817+
*
818+
* This structure describes a top-level JSON array whose elements may be
819+
* of different types (primitives, objects, arrays, or nested mixed arrays).
820+
* Each element in the array is described by an entry in a descriptor array.
821+
*
822+
* Mixed arrays are useful for parsing and encoding JSON arrays that do not
823+
* have a homogeneous element type, such as:
824+
*
825+
* [ "string", 42, { "foo": 1 }, [1,2,3], true ]
826+
*
827+
* @note This structure and its associated macros are intended for use with
828+
* the mixed array parsing and encoding APIs (see json_mixed_arr_parse()).
829+
*/
830+
struct json_mixed_arr_descr {
831+
uint32_t type : 7;
832+
size_t count_offset;
833+
834+
union {
835+
struct {
836+
size_t offset;
837+
size_t size;
838+
} primitive;
839+
840+
struct {
841+
const struct json_obj_descr *sub_descr;
842+
size_t sub_descr_len;
843+
size_t offset;
844+
} object;
845+
846+
struct {
847+
const struct json_obj_descr *element_descr;
848+
size_t n_elements;
849+
size_t offset;
850+
} array;
851+
852+
struct {
853+
const struct json_mixed_arr_descr *sub_descr;
854+
size_t sub_descr_len;
855+
size_t offset;
856+
} mixed_array;
857+
};
858+
};
859+
860+
/**
861+
* @brief Helper macro to declare a mixed array primitive element descriptor.
862+
*
863+
* @param struct_ Struct containing the value.
864+
* @param field_name_ Field name in the struct.
865+
* @param type_ Token type for the JSON value (see enum json_tokens).
866+
* @param count_field_ Field name in the struct for the number of elements.
867+
*
868+
* Example:
869+
* struct foo { int x; size_t x_count; };
870+
* const struct json_mixed_arr_descr foo_descr[] = {
871+
* JSON_MIXED_ARR_DESCR_PRIM(struct foo, x, JSON_TOK_NUMBER, x_count),
872+
* };
873+
*/
874+
#define JSON_MIXED_ARR_DESCR_PRIM(struct_, field_name_, type_, count_field_) \
875+
{ \
876+
.type = type_, \
877+
.count_offset = offsetof(struct_, count_field_), \
878+
.primitive = { \
879+
.offset = offsetof(struct_, field_name_), \
880+
.size = SIZEOF_FIELD(struct_, field_name_) \
881+
} \
882+
}
883+
884+
/**
885+
* @brief Helper macro to declare a mixed array object element descriptor.
886+
*
887+
* @param struct_ Struct containing the object.
888+
* @param field_name_ Field name in the struct.
889+
* @param sub_descr_ Array of json_obj_descr describing the object fields.
890+
* @param count_field_ Field name in the struct for the number of elements.
891+
*
892+
* Example:
893+
* struct bar { int y; };
894+
* struct foo { struct bar b; size_t b_count; };
895+
* const struct json_obj_descr bar_descr[] = { ... };
896+
* const struct json_mixed_arr_descr foo_descr[] = {
897+
* JSON_MIXED_ARR_DESCR_OBJECT(struct foo, b, bar_descr, b_count),
898+
* };
899+
*/
900+
#define JSON_MIXED_ARR_DESCR_OBJECT(struct_, field_name_, sub_descr_, count_field_) \
901+
{ \
902+
.type = JSON_TOK_OBJECT_START, \
903+
.count_offset = offsetof(struct_, count_field_), \
904+
.object = { \
905+
.sub_descr = sub_descr_, \
906+
.sub_descr_len = ARRAY_SIZE(sub_descr_), \
907+
.offset = offsetof(struct_, field_name_) \
908+
} \
909+
}
910+
911+
/**
912+
* @brief Helper macro to declare a mixed array homogeneous array element descriptor.
913+
*
914+
* @param struct_ Struct containing the array.
915+
* @param field_name_ Field name in the struct.
916+
* @param max_len_ Maximum number of elements in the array.
917+
* @param elem_descr_ Element descriptor (pointer to json_obj_descr array).
918+
* @param count_field_ Field name in the struct for the number of elements.
919+
*
920+
* Example:
921+
* struct foo {
922+
* int arr[4];
923+
* size_t arr_count;
924+
* };
925+
* const struct json_obj_descr arr_elem_descr[] = {
926+
* JSON_OBJ_DESCR_ARRAY(struct foo, arr, 4, arr_count, JSON_TOK_NUMBER),
927+
* };
928+
* const struct json_mixed_arr_descr foo_descr[] = {
929+
* JSON_MIXED_ARR_DESCR_ARRAY(struct foo, arr, 4, arr_elem_descr, arr_count),
930+
* };
931+
*/
932+
#define JSON_MIXED_ARR_DESCR_ARRAY(struct_, field_name_, max_len_, elem_descr_, count_field_) \
933+
{ \
934+
.type = JSON_TOK_ARRAY_START, \
935+
.count_offset = offsetof(struct_, count_field_), \
936+
.array = { \
937+
.element_descr = elem_descr_, \
938+
.n_elements = (max_len_), \
939+
.offset = offsetof(struct_, field_name_) \
940+
} \
941+
}
942+
943+
/**
944+
* @brief Helper macro to declare a nested mixed array element descriptor.
945+
*
946+
* @param struct_ Struct containing the nested mixed array.
947+
* @param field_name_ Field name in the struct.
948+
* @param sub_descr_ Mixed array descriptor for the nested array.
949+
* @param count_field_ Field name in the struct for the number of elements.
950+
*
951+
* Example:
952+
* struct foo { ...; size_t nested_count; };
953+
* const struct json_mixed_arr_descr nested_descr[] = { ... };
954+
* const struct json_mixed_arr_descr foo_descr[] = {
955+
* JSON_MIXED_ARR_DESCR_MIXED_ARRAY(struct foo, nested, nested_descr, nested_count),
956+
* };
957+
*/
958+
#define JSON_MIXED_ARR_DESCR_MIXED_ARRAY(struct_, field_name_, sub_descr_, count_field_) \
959+
{ \
960+
.type = JSON_TOK_MIXED_ARRAY, \
961+
.count_offset = offsetof(struct_, count_field_), \
962+
.mixed_array = { \
963+
.sub_descr = sub_descr_, \
964+
.sub_descr_len = ARRAY_SIZE(sub_descr_), \
965+
.offset = offsetof(struct_, field_name_) \
966+
} \
967+
}
968+
969+
/**
970+
* @brief Parse a JSON mixed array into a C structure.
971+
*
972+
* This function parses a JSON array (which may contain elements of varying types)
973+
* according to the provided mixed array descriptor and stores the result in the
974+
* user-supplied structure.
975+
*
976+
* @param json Pointer to the input JSON string.
977+
* @param len Length of the input JSON string.
978+
* @param descr Descriptor array describing the structure of the mixed array.
979+
* @param descr_len Number of elements in the descriptor array.
980+
* @param val Pointer to the structure to populate with parsed data.
981+
*
982+
* @return < 0 if error, number of elements parsed on success.
983+
*/
984+
int json_mixed_arr_parse(char *json, size_t len,
985+
const struct json_mixed_arr_descr *descr,
986+
size_t descr_len, void *val);
987+
988+
/**
989+
* @brief Encode a C structure as a JSON mixed array.
990+
*
991+
* This function encodes a C structure, described by the mixed array descriptor,
992+
* as a JSON array.
993+
*
994+
* @param descr Descriptor array describing the structure of the mixed array.
995+
* @param descr_len Number of elements in the descriptor array.
996+
* @param val Pointer to the structure to encode.
997+
* @param append_bytes Function to append bytes to the output
998+
* @param data Data pointer to be passed to the append_bytes callback
999+
* function.
1000+
*
1001+
* @return 0 if mixed array has been successfully encoded. Negative error code on failure.
1002+
*/
1003+
int json_mixed_arr_encode(const struct json_mixed_arr_descr *descr,
1004+
size_t descr_len, void *val,
1005+
json_append_bytes_t append_bytes,
1006+
void *data);
1007+
1008+
/**
1009+
* @brief Encode a C structure as a JSON mixed array into a buffer.
1010+
*
1011+
* This function encodes a C structure, described by the mixed array descriptor,
1012+
* as a JSON array and writes the result into the provided buffer.
1013+
*
1014+
* @param descr Descriptor array describing the structure of the mixed array.
1015+
* @param descr_len Number of elements in the descriptor array.
1016+
* @param val Pointer to the structure to encode.
1017+
* @param buffer Output buffer to write the JSON string.
1018+
* @param buf_size Size of the output buffer.
1019+
*
1020+
* @return 0 if mixed array has been successfully encoded. Negative error code on failure.
1021+
*/
1022+
int json_mixed_arr_encode_buf(const struct json_mixed_arr_descr *descr,
1023+
size_t descr_len, void *val,
1024+
char *buffer, size_t buf_size);
1025+
1026+
/**
1027+
* @brief Calculate the length of the encoded JSON mixed array.
1028+
*
1029+
* This function calculates the number of bytes required to encode the given
1030+
* structure as a JSON mixed array, according to the provided descriptor.
1031+
*
1032+
* @param descr Descriptor array describing the structure of the mixed array.
1033+
* @param descr_len Number of elements in the descriptor array.
1034+
* @param val Pointer to the structure to encode.
1035+
*
1036+
* @return Number of bytes required for encoding, or negative error code.
1037+
*/
1038+
ssize_t json_calc_mixed_arr_len(const struct json_mixed_arr_descr *descr,
1039+
size_t descr_len, void *val);
1040+
8141041
#ifdef __cplusplus
8151042
}
8161043
#endif

0 commit comments

Comments
 (0)