项目作者: Holixus

项目描述 :
A small footprint(code and memory) simple JSON parsing C library for embedded projects
高级语言: C
项目地址: git://github.com/Holixus/nanojson.git
创建时间: 2019-12-16T10:49:26Z
项目社区:https://github.com/Holixus/nanojson

开源协议:GNU General Public License v3.0

下载


nanojson

A small footprint(code and memory) simple JSON parsing C library for embedded projects

  • 64 bits integers(optional)
  • Hexadecimal(“0x”) integers(optional)
  • Good tests coverage
  • Buildable without float/double support
  • Ability to parse JSON text without malloc usage

Build

  1. # cmake -DJSON_64BITS_INTEGERS=OFF -DJSON_HEX_NUMBERS=OFF -DJSON_FLOATS=OFF.
  2. # make

Build options

  • BUILD_SHARED_LIBRARY(OFF) — Build shared library (not only static)
  • JSON_64BITS_INTEGERS(OFF) — Enable support of 64 bits integers
  • JSON_HEX_NUMBERS(OFF) — Enabled support of 0x integers
  • JSON_FLOATS(OFF) — Enable support of Floating point Numbers
  • JSON_SHORT_NEXT(OFF) — Use short type for next field of jsn_t
  • JSON_PACKED(OFF) — Use packed json item structure

  • JSON_AUTO_PARSE_FN(ON) — Build json_auto_parse() function

    • JSON_AUTO_PARSE_POOL_START_SIZE(32) — Initial jsn_t array size
    • JSON_AUTO_PARSE_POOL_INCREASE(n+32) — Increase jsn_t array size formula
  • JSON_STRINGIFY_FN(ON) — Build json_stringify() function

  • JSON_GET_FN(ON) — Build json_get() function

    • JSON_MAX_ID_LENGTH(64) — Maximum identifiers length in path for json_get function
  • BUILD_TESTS(ON) — Build tests application

Include files

  1. #include <nano/json.h>

Nodes types

  1. typedef
  2. enum {
  3. JS_UNDEFINED=1, JS_NULL, JS_BOOLEAN, JS_NUMBER, JS_FLOAT, JS_STRING, JS_ARRAY, JS_OBJECT
  4. } nj_type_t;

jsn_t

  1. #ifdef JSON_64BITS_INTEGERS
  2. typedef int64_t jsn_number_t;
  3. #else
  4. typedef int32_t jsn_number_t;
  5. #endif
  6. #ifdef JSON_SHORT_NEXT
  7. typedef short jsn_next_t;
  8. #else
  9. typedef int jsn_next_t;
  10. #endif
  11. typedef
  12. struct jsn {
  13. union {
  14. char *string; /* string id of the node in the parent object */
  15. unsigned int number; /* integer index of the node in the parent array */
  16. } id;
  17. union {
  18. jsn_number_t number;
  19. char *string;
  20. jsn_next_t length; /* number of object/array elements */
  21. #ifdef JSON_FLOATS
  22. double floating;
  23. #endif
  24. } data;
  25. jsn_next_t next; /* index offset to next sibling node (0 - parent node offset) */
  26. char id_type; /* type of id. JS_NUMBER(for array) or JS_STRING(for object) */
  27. char type; /* type of data (nj_type_t) */
  28. }
  29. #ifdef JSON_PACKED
  30. __attribute__((packed))
  31. #endif
  32. jsn_t;

Functions

int json_parse(jsn_t *pool, size_t size, char *text)

  • pool — pointer to (somewhere allocated) array of jsn_t elements
  • size — number of pool elements
  • text — JSON text source. Will be corrupted because all strings will be stored in this buffer.

Parse JSON text to array of nodes. The first node is always root node. If parsing made succesfully
then source text memory will be used for storing of values identifiers and strings.
Please, don’t forget this.

Return value

The function return a number of used jsn_t elements of array pointed by pool argument.

On error, negative value is returned, and errno is set appropriately.

Errors

  • ENOMEM passed array of jsn_t elements is not enough for store parsed JSON data tree.
  • EINVAL impossible to parse passed JSON text. The returned negative value is offset to broken
    place of JSON code and text buffer will not be corrupted by parsing.

Example

  1. jsn_t json[100];
  2. int len = json_parse(json, sizeof json / sizeof json[0], text);
  3. if (len < 0) {
  4. perror("json_parse");
  5. ...
  6. }
  7. ...

jsn_t *json_auto_parse(char *text, char **end)

  • text — JSON text source. Will be corrupted because all strings will be stored in this buffer.
  • end — in case of parsing error by the .

Parse JSON text.

Return value

The function return a pointer to array jsn_t elements. Should be released by free().

On error, NULL is returned, and errno is set appropriately.

Errors

  • ENOMEM Out of memory.
  • EINVAL impossible to parse passed JSON text. If end is not NULL, a pointer to broken
    JSON code will be stored in the pointer referenced by end. The text buffer will not be corrupted by parser.

Example

  1. char *err_pos;
  2. jsn_t *json = json_auto_parse(text, &err_pos);
  3. if (!json) {
  4. if (errno == EINVAL) {
  5. char crop[50];
  6. snprintf(crop, sizeof crop, "%s", err_pos);
  7. perror("json_auto_parse: JSON syntax error at the code '%s'", crop);
  8. } else
  9. perror("json_auto_parse");
  10. return -1;
  11. }
  12. ...
  13. free(json);

char *json_stringify(char *out, size_t size, jsn_t *root)

  • outbuf — output buffer for JSON text
  • size — size of output buffer including terminating zero
  • root — root element of json tree

Convert parsed JSON tree back to text. May be useful for debugging purpose.

Return value

Return pointer to output buffer.

Example

  1. int source_len = strlen(source);
  2. jsn_t *json = json_auto_parse(source, NULL);
  3. if (!json)
  4. return -1;
  5. char string[source_len * 2];
  6. json_stringify(string, sizeof string, json);
  7. free(json);
  8. printf("JSON: %s\n", string);
  9. return 0;

jsn_t *json_item(jsn_t *node, char const *id)

  • node — object json node to search element
  • id — string identifier of object element

Returns element of object with id or NULL if absent.

Errors

  • ENOENT there is no element with id value.
  • ENOTDIR the node is not object type.

jsn_t *json_cell(jsn_t *node, int index)

  • node — array json node to search element
  • index — index of array element

Returns element of array with index or NULL if absent.

Errors

  • ENOENT there is no element with index value.
  • ENOTDIR the node is not array type.

jsn_t *json_get(jsn_t *node, char const *path)

  • node — array json node to search element
  • path — qualified path of JSON item

Returns element of json with path or NULL if absent. If path is empty string then returns the node value.

Errors

  • ENOENT there is no element in path.
  • ENOTDIR wrong node type in path.
  • EINVAL impossible to parse passed path.

Sample

  1. char const json[] =
  2. "{"
  3. "\"0\":\"value\","
  4. "\"key\":555,"
  5. "\"array\":["
  6. "0,1,2,3,4,5"
  7. "],"
  8. "\"obj\":{"
  9. "\"ololo\":["
  10. "\"a\",\"b\",{"
  11. "\"key\":123"
  12. "}"
  13. "]"
  14. "}"
  15. "}";
  16. jsn_t j[100];
  17. int len = json_parse(j, sizeof j / sizeof j[0], json);
  18. if (len < 0) {
  19. perror("json_parse");
  20. // ...
  21. }
  22. char const *z = json_string(json_get(j, "[\"0\"]")); // "value"
  23. int n0 = json_number(json_get(j, ".key")); // 555
  24. int n1 = json_number(json_get(j, "[\"key\"]")); // 555
  25. jsn_t *array = json_get(j, ".array"); // [0,1,2,3,4,5]
  26. int n2 = json_number(json_get(j, ".array[3]")); // 3
  27. char const *z = json_string(json_get(j, ".obj.ololo[1]"); // "\"b\"",
  28. jsn_t *ololo2 = json_get(j, ".obj.ololo[2]"); // "{\"key\":123}",
  29. int n3 = json_number(json_get(j, ".obj.ololo[2].key"); // "123"
  30. // ...

char const *json_string(jsn_t *node, char const *missed_value)

  • node — pointer to json node
  • missed_value — default value if node is undefined (NULL)

Returns pointer to string value of node. For non JS_STRING node will be casted
to static buffer string.

If node is NULL returns missed_value.

int json_boolean(jsn_t *node, int missed_value)

  • node — pointer to json node
  • missed_value — default value if node is undefined (NULL)

Returns boolean(1 or 0) value of node. Non JS_BOOLEAN node will be casted
to boolean by JS type convertation rules.

If node is NULL returns missed_value.

int json_number(jsn_t *node, int missed_value)

  • node — pointer to json node
  • missed_value — default value if node is undefined (NULL)

Returns integer value of node. Non JS_NUMBER node will be casted
by JS type convertation rules.

If node is NULL returns missed_value.

double json_float(jsn_t *node, double missed_value)

  • node — pointer to json node
  • missed_value — default value if node is undefined (NULL)

Returns floating pointer(double) value of node. Non JS_FLOAT node will be casted
by JS type convertation rules.

If node is NULL returns missed_value.

json_foreach

For enumerating of child nodes of JS_OBJECT/JS_ARRAY object you can use json_foreach macro-definition.

  1. jsn_t *obj = json_auto_parse("[1,2,3,4,5]");
  2. json_foreach(obj, offset) {
  3. jsn_t *node = obj + offset;
  4. printf("obj[%d] = '%s'\n", node->id.index, json_string(node));
  5. }
  6. free(obj);

Big code example

  1. static int test_gets()
  2. {
  3. char ser[4096];
  4. char *text = strdup("\
  5. [\
  6. {\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"capabilities\",\"params\":{}},\
  7. {\"jsonrpc\":\"2.0\",\"id\":\"1\",\"method\":\"ololo\",\"params\":523424}\
  8. ]");
  9. printf("test_gets\n");
  10. jsn_t json[100];
  11. int len = json_parse(json, 100, text);
  12. if (len < 0) {
  13. perror("json_obj_scan parse");
  14. free(text);
  15. return 1;
  16. }
  17. printf("parsed %d nodes\n", len);
  18. json_foreach(json, offset) {
  19. jsn_t *node = json + offset;
  20. char const *version = json_string(json_item(node, "jsonrpc"), "0");
  21. char const *method = json_string(json_item(node, "method"), NULL);
  22. int id = json_number(json_item(node, "id"), -1);
  23. jsn_t *params = json_item(node, "params");
  24. printf("[%d]: version: %s, id: %d, method: %s, params: %s\n",
  25. node->id.index, version, id, method, json_stringify(ser, sizeof ser, params));
  26. }
  27. free(text);
  28. return 0;
  29. }