{"id":22246462,"url":"https://github.com/holixus/nanojson","last_synced_at":"2026-05-03T19:33:51.105Z","repository":{"id":86328036,"uuid":"228365358","full_name":"Holixus/nanojson","owner":"Holixus","description":"A small footprint(code and memory) simple JSON parsing C library for embedded projects","archived":false,"fork":false,"pushed_at":"2023-02-10T17:35:44.000Z","size":70,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T11:27:41.472Z","etag":null,"topics":["json","json-parser"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Holixus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-12-16T10:49:26.000Z","updated_at":"2023-02-10T17:20:19.000Z","dependencies_parsed_at":null,"dependency_job_id":"ac1c052d-468c-4cf6-922a-03354c36aa37","html_url":"https://github.com/Holixus/nanojson","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/Holixus/nanojson","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Holixus%2Fnanojson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Holixus%2Fnanojson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Holixus%2Fnanojson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Holixus%2Fnanojson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Holixus","download_url":"https://codeload.github.com/Holixus/nanojson/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Holixus%2Fnanojson/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32582780,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","json-parser"],"created_at":"2024-12-03T05:27:46.265Z","updated_at":"2026-05-03T19:33:51.090Z","avatar_url":"https://github.com/Holixus.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nanojson\nA small footprint(code and memory) simple [JSON](https://www.rfc-editor.org/rfc/rfc8259.html) parsing C library for embedded projects\n\n* 64 bits integers(optional)\n* Hexadecimal(\"0x\") integers(optional)\n* Good tests coverage\n* Buildable without float/double support\n* Ability to parse JSON text without malloc usage\n\n# Build\n\n```\n# cmake -DJSON_64BITS_INTEGERS=OFF -DJSON_HEX_NUMBERS=OFF -DJSON_FLOATS=OFF.\n# make\n```\n\n## Build options\n\n* `BUILD_SHARED_LIBRARY`(OFF) -- Build shared library (not only static)\n* `JSON_64BITS_INTEGERS`(OFF) -- Enable support of 64 bits integers\n* `JSON_HEX_NUMBERS`(OFF) -- Enabled support of 0x integers\n* `JSON_FLOATS`(OFF) -- Enable support of Floating point Numbers\n* `JSON_SHORT_NEXT`(OFF) -- Use `short` type for next field of jsn_t\n* `JSON_PACKED`(OFF) -- Use packed json item structure\n\n* `JSON_AUTO_PARSE_FN`(ON) -- Build json_auto_parse() function\n  * `JSON_AUTO_PARSE_POOL_START_SIZE`(32) -- Initial jsn_t array size\n  * `JSON_AUTO_PARSE_POOL_INCREASE`(n+32) -- Increase jsn_t array size formula\n\n* `JSON_STRINGIFY_FN`(ON) -- Build json_stringify() function\n\n* `JSON_GET_FN`(ON) -- Build json_get() function\n  * `JSON_MAX_ID_LENGTH`(64) -- Maximum identifiers length in path for json_get function\n\n* `BUILD_TESTS`(ON) -- Build tests application\n\n# Include files\n\n```c\n#include \u003cnano/json.h\u003e\n```\n\n# Nodes types\n\n```c\ntypedef\nenum {\n\tJS_UNDEFINED=1, JS_NULL, JS_BOOLEAN, JS_NUMBER, JS_FLOAT, JS_STRING, JS_ARRAY, JS_OBJECT\n} nj_type_t;\n```\n# jsn_t\n\n```c\n#ifdef JSON_64BITS_INTEGERS\ntypedef int64_t jsn_number_t;\n#else\ntypedef int32_t jsn_number_t;\n#endif\n\n#ifdef JSON_SHORT_NEXT\ntypedef short jsn_next_t;\n#else\ntypedef int jsn_next_t;\n#endif\n\n\ntypedef\nstruct jsn {\n\tunion {\n\t\tchar *string;        /* string id of the node in the parent object    */\n\t\tunsigned int number; /* integer index of the node in the parent array */\n\t} id;\n\tunion {\n\t\tjsn_number_t number;\n\t\tchar *string;\n\t\tjsn_next_t length;   /* number of object/array elements */\n#ifdef JSON_FLOATS\n\t\tdouble floating;\n#endif\n\t} data;\n\tjsn_next_t next;         /* index offset to next sibling node (0 - parent node offset) */\n\tchar id_type;            /* type of id. JS_NUMBER(for array) or JS_STRING(for object)  */\n\tchar type;               /* type of data (nj_type_t)                                   */\n}\n#ifdef JSON_PACKED\n__attribute__((packed))\n#endif\njsn_t;\n```\n\n\n# Functions\n\n## `int json_parse(jsn_t *pool, size_t size, char *text)`\n\n* `pool` -- pointer to (somewhere allocated) array of `jsn_t` elements\n* `size` -- number of pool elements\n* `text` -- JSON text source. Will be corrupted because all strings will be stored in this buffer.\n\nParse JSON text to array of nodes. The first node is always root node. If parsing made succesfully\nthen source text memory will be used for storing of values identifiers and strings.\nPlease, don't forget this.\n\n\n### Return value\n\nThe function return a number of used `jsn_t` elements of array pointed by `pool` argument.\n\nOn error, negative value is returned, and errno is set appropriately.\n\n### Errors\n\n* `ENOMEM` passed array of `jsn_t` elements is not enough for store parsed JSON data tree.\n* `EINVAL` impossible to parse passed JSON text. The returned negative value is offset to broken\nplace of JSON code and text buffer will not be corrupted by parsing.\n\n\n### Example\n```c\n\tjsn_t json[100];\n\tint len = json_parse(json, sizeof json / sizeof json[0], text);\n\tif (len \u003c 0) {\n\t\tperror(\"json_parse\");\n\t\t...\n\t}\n\t...\n\n```\n\n\n\n## `jsn_t *json_auto_parse(char *text, char **end)`\n\n* `text` -- JSON text source. Will be corrupted because all strings will be stored in this buffer.\n* `end` -- in case of parsing error by the .\n\nParse JSON `text`.\n\n### Return value\n\nThe function return a pointer to array `jsn_t` elements. Should be released by `free()`.\n\nOn error, NULL is returned, and errno is set appropriately.\n\n### Errors\n\n* `ENOMEM` Out of memory.\n* `EINVAL` impossible to parse passed JSON text. If `end` is not NULL, a pointer to broken\nJSON code will be stored in the pointer referenced by `end`. The text buffer will not be corrupted by parser.\n\n\n### Example\n```c\n\tchar *err_pos;\n\tjsn_t *json = json_auto_parse(text, \u0026err_pos);\n\tif (!json) {\n\t\tif (errno == EINVAL) {\n\t\t\tchar crop[50];\n\t\t\tsnprintf(crop, sizeof crop, \"%s\", err_pos);\n\t\t\tperror(\"json_auto_parse: JSON syntax error at the code '%s'\", crop);\n\t\t} else\n\t\t\tperror(\"json_auto_parse\");\n\t\treturn -1;\n\t}\n\t...\n\tfree(json);\n```\n\n\n\n## `char *json_stringify(char *out, size_t size, jsn_t *root)`\n\n* `outbuf` -- output buffer for JSON text\n* `size` -- size of output buffer including terminating zero\n* `root` -- root element of json tree\n\nConvert parsed JSON tree back to text. May be useful for debugging purpose.\n\n### Return value\n\nReturn pointer to output buffer.\n\n### Example\n\n```c\n\tint source_len = strlen(source);\n\tjsn_t *json = json_auto_parse(source, NULL);\n\tif (!json)\n\t\treturn -1;\n\n\tchar string[source_len * 2];\n\tjson_stringify(string, sizeof string, json);\n\n\tfree(json);\n\n\tprintf(\"JSON: %s\\n\", string);\n\treturn 0;\n```\n\n\n## `jsn_t *json_item(jsn_t *node, char const *id)`\n\n* `node` -- object json node to search element\n* `id` -- string identifier of object element\n\nReturns element of object with `id` or NULL if absent.\n\n### Errors\n\n* `ENOENT` there is no element with `id` value.\n* `ENOTDIR` the `node` is not object type.\n\n\n## `jsn_t *json_cell(jsn_t *node, int index)`\n\n* `node` -- array json node to search element\n* `index` -- index of array element\n\nReturns element of array with `index` or NULL if absent.\n\n### Errors\n\n* `ENOENT` there is no element with `index` value.\n* `ENOTDIR` the `node` is not array type.\n\n\n## `jsn_t *json_get(jsn_t *node, char const *path)`\n\n* `node` -- array json node to search element\n* `path` -- qualified path of JSON item\n\nReturns element of json with `path` or NULL if absent. If `path` is empty string then returns the `node` value.\n\n### Errors\n\n* `ENOENT` there is no element in `path`.\n* `ENOTDIR` wrong node type in path.\n* `EINVAL` impossible to parse passed `path`.\n\n### Sample\n\n```c\n\tchar const json[] = \n\t\"{\"\n\t\t\"\\\"0\\\":\\\"value\\\",\"\n\t\t\"\\\"key\\\":555,\"\n\t\t\"\\\"array\\\":[\"\n\t\t\t\"0,1,2,3,4,5\"\n\t\t\"],\"\n\t\t\"\\\"obj\\\":{\"\n\t\t\t\"\\\"ololo\\\":[\"\n\t\t\t\t\"\\\"a\\\",\\\"b\\\",{\"\n\t\t\t\t\t\"\\\"key\\\":123\"\n\t\t\t\t\"}\"\n\t\t\t\"]\"\n\t\t\"}\"\n\t\"}\";\n\n\tjsn_t j[100];\n\tint len = json_parse(j, sizeof j / sizeof j[0], json);\n\tif (len \u003c 0) {\n\t\tperror(\"json_parse\");\n\t\t// ...\n\t}\n\n\tchar const *z = json_string(json_get(j, \"[\\\"0\\\"]\"));      // \"value\"\n\tint n0 = json_number(json_get(j, \".key\"));                // 555\n\tint n1 = json_number(json_get(j, \"[\\\"key\\\"]\"));           // 555\n\tjsn_t *array = json_get(j, \".array\");                     // [0,1,2,3,4,5]\n\tint n2 = json_number(json_get(j, \".array[3]\"));           // 3\n\tchar const *z = json_string(json_get(j, \".obj.ololo[1]\"); // \"\\\"b\\\"\",\n\tjsn_t *ololo2 = json_get(j, \".obj.ololo[2]\");             // \"{\\\"key\\\":123}\",\n\tint n3 = json_number(json_get(j, \".obj.ololo[2].key\");    // \"123\"\n\t// ...\n```\n\n\n## `char const *json_string(jsn_t *node, char const *missed_value)`\n\n* `node` -- pointer to json node\n* `missed_value` -- default value if node is undefined (NULL)\n\nReturns pointer to string value of node. For non JS_STRING node will be casted\nto static buffer string.\n\nIf node is NULL returns `missed_value`.\n\n\n\n## `int json_boolean(jsn_t *node, int missed_value)`\n\n* `node` -- pointer to json node\n* `missed_value` -- default value if node is undefined (NULL)\n\nReturns boolean(1 or 0) value of node. Non JS_BOOLEAN node will be casted \nto boolean by JS type convertation rules.\n\nIf node is NULL returns `missed_value`.\n\n\n## `int json_number(jsn_t *node, int missed_value)`\n\n* `node` -- pointer to json node\n* `missed_value` -- default value if node is undefined (NULL)\n\nReturns integer value of node. Non JS_NUMBER node will be casted \nby JS type convertation rules.\n\nIf node is NULL returns `missed_value`.\n\n\n## `double json_float(jsn_t *node, double missed_value)`\n\n* `node` -- pointer to json node\n* `missed_value` -- default value if node is undefined (NULL)\n\nReturns floating pointer(double) value of node. Non JS_FLOAT node will be casted \nby JS type convertation rules.\n\n\nIf node is NULL returns `missed_value`.\n\n\n## `json_foreach`\n\nFor enumerating of child nodes of JS_OBJECT/JS_ARRAY object you can use `json_foreach` macro-definition.\n\n\n```c\n\tjsn_t *obj = json_auto_parse(\"[1,2,3,4,5]\");\n\tjson_foreach(obj, offset) {\n\t\tjsn_t *node = obj + offset;\n\t\tprintf(\"obj[%d] = '%s'\\n\", node-\u003eid.index, json_string(node));\n\t}\n\tfree(obj);\n```\n\n\n# Big code example\n\n```c\nstatic int test_gets()\n{\n\tchar ser[4096];\n\tchar *text = strdup(\"\\\n[\\\n {\\\"jsonrpc\\\":\\\"2.0\\\",\\\"id\\\":\\\"0\\\",\\\"method\\\":\\\"capabilities\\\",\\\"params\\\":{}},\\\n {\\\"jsonrpc\\\":\\\"2.0\\\",\\\"id\\\":\\\"1\\\",\\\"method\\\":\\\"ololo\\\",\\\"params\\\":523424}\\\n]\");\n\n\tprintf(\"test_gets\\n\");\n\n\tjsn_t json[100];\n\tint len = json_parse(json, 100, text);\n\tif (len \u003c 0) {\n\t\tperror(\"json_obj_scan parse\");\n\t\tfree(text);\n\t\treturn 1;\n\t}\n\n\tprintf(\"parsed %d nodes\\n\", len);\n\n\tjson_foreach(json, offset) {\n\t\tjsn_t *node = json + offset;\n\n\t\tchar const *version = json_string(json_item(node, \"jsonrpc\"), \"0\");\n\t\tchar const *method  = json_string(json_item(node, \"method\"), NULL);\n\t\tint id              = json_number(json_item(node, \"id\"), -1);\n\t\tjsn_t *params       =             json_item(node, \"params\");\n\n\t\tprintf(\"[%d]: version: %s, id: %d, method: %s, params: %s\\n\",\n\t\t       node-\u003eid.index, version, id, method, json_stringify(ser, sizeof ser, params));\n\t}\n\tfree(text);\n\treturn 0;\n}\n\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fholixus%2Fnanojson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fholixus%2Fnanojson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fholixus%2Fnanojson/lists"}