{"id":46848728,"url":"https://github.com/garrisonhh/ghh_json","last_synced_at":"2026-03-10T15:35:47.939Z","repository":{"id":47627698,"uuid":"398030803","full_name":"garrisonhh/ghh_json","owner":"garrisonhh","description":"single-header, programmer-friendly json library for C99 and C++","archived":false,"fork":false,"pushed_at":"2024-12-27T00:59:45.000Z","size":121,"stargazers_count":22,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-12-27T01:18:04.773Z","etag":null,"topics":["c","c99","cpp","programmer-friendly"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/garrisonhh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-19T17:56:34.000Z","updated_at":"2024-12-27T00:57:12.000Z","dependencies_parsed_at":"2022-07-22T12:32:34.872Z","dependency_job_id":null,"html_url":"https://github.com/garrisonhh/ghh_json","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/garrisonhh/ghh_json","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrisonhh%2Fghh_json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrisonhh%2Fghh_json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrisonhh%2Fghh_json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrisonhh%2Fghh_json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garrisonhh","download_url":"https://codeload.github.com/garrisonhh/ghh_json/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garrisonhh%2Fghh_json/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30340117,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T15:03:31.997Z","status":"ssl_error","status_checked_at":"2026-03-10T15:01:30.431Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["c","c99","cpp","programmer-friendly"],"created_at":"2026-03-10T15:35:47.783Z","updated_at":"2026-03-10T15:35:47.907Z","avatar_url":"https://github.com/garrisonhh.png","language":"C","readme":"# ghh_json.h\n\na single-header ISO-C99 (and C++ compatible) json loader.\n\n## why?\n\nobviously this isn't the first json library written for C, so why would I write\nthis?\n\n1. easy build\n\nthere are great json C libraries with clean APIs and many more features than my\nimplementation out there, but they require build system integration which\nimmediately adds work I don't want to deal with.\n\n2. easy usage\n\nthere are other single-header json libraries for C out there, but I wasn't super\ninto the way they are structured. I wrote this the way I would expect a json\nlibrary to behave. this is more of a taste thing than anything, if you don't\nlike how ghh_json works check out another implementation.\n\n## usage\n\n**note: ghh_json does not currently support unicode escape sequences, like**\n**\"\\\\u0123\". otherwise it is json specification conforming.**\n\n[also see examples](https://github.com/garrisonhh/ghh_json#examples)\n\nto include in your project:\n\n```c\n#define GHH_JSON_IMPL\n#include \"ghh_json.h\"\n```\n\nthe basic program structure looks like this:\n\n```c\njson_t json;\njson_load_file(\u0026json, \"mydata.json\");\n\n// do stuff ...\n\njson_unload(\u0026json);\n```\n\nthere are only 3 types you need to think about:\n- `json_type_e`, json type enum\n  - types are: `JSON_OBJECT`, `JSON_ARRAY`, `JSON_STRING`, `JSON_NUMBER`,\n  `JSON_TRUE`, `JSON_FALSE`, `JSON_NULL`\n- `json_object_t`, a tagged union\n  - access type through `.type`\n  - access and modify data using `json_get`, `json_put`, and `json_pop`\n  functions\n- `json_t`, a reusable memory context for json objects which acts as an\n  arena/bump allocator\n  - access root element through `.root`.\n  - when unloaded, all memory associated with it is freed - so you don't need\n  to explicitly manage individual `json_object_t *`s.\n    - *when working with multiple `json_t` contexts, be aware that you can\n    create use-after-free bugs if you unload an object referenced by an object\n    on a different context. stay aware of your lifetimes, and use copy functions\n    when you need to!*\n\n## api\n\n### settings\n\n```c\n// define your own allocation functions\n#define JSON_MALLOC(size)\n#define JSON_FREE(size)\n\n// change the size of the char buffer for fread()\n#define JSON_FREAD_BUF_SIZE\n\n// the json_t allocator works by allocating pages to accommodate objects and\n// data. increasing this means less allocations during parsing\n#define JSON_PAGE_SIZE\n```\n\n### json\\_t lifetime\n\n```c\n// load json from a string\nvoid json_load(json_t *, char *text);\n// create an empty json_t context\nvoid json_load_empty(json_t *);\n// load json from a file\nvoid json_load_file(json_t *, const char *filepath);\n// free all memory associated with json context\nvoid json_unload(json_t *);\n```\n\n### data access\n\n```c\n// returns a string allocated with JSON_MALLOC\n// if mini, won't add newlines or indentation\nchar *json_serialize(json_object_t *, bool mini, int indent, size_t *out_len);\n\n// retrieve a key from an object\n// if NDEBUG is not defined, will type check the root object\njson_object_t *json_get_object(json_object_t *, char *key);\n// returns actual, mutable array pointer\njson_object_t **json_get_array(json_object_t *, char *key, size_t *out_size);\nchar *json_get_string(json_object_t *, char *key);\ndouble json_get_number(json_object_t *, char *key);\nbool json_get_bool(json_object_t *, char *key);\n\n// cast an object to a type\n// if NDEBUG is not defined, will type check the object\njson_object_t **json_to_array(json_object_t *, size_t *out_size);\nchar *json_to_string(json_object_t *);\ndouble json_to_number(json_object_t *);\nbool json_to_bool(json_object_t *);\n```\n\n### data modification\n\n```c\n// remove a json_object from another json_object (unordered)\njson_object_t *json_pop(json_t *, json_object_t *, char *key);\n// pop but ordered, this is O(n) rather than O(1) removal time\njson_object_t *json_pop_ordered(json_t *, json_object_t *, char *key);\n\n// add a json_object to another json_object\nvoid json_put(json_t *, json_object_t *, char *key, json_object_t *child);\n\n// create a new json type on a json_t, and add it to an object\njson_object_t *json_put_object(json_t *, json_object_t *, char *key);\nvoid json_put_array(\n\tjson_t *, json_object_t *, json_object_t **objects, size_t size\n);\nvoid json_put_string(json_t *, json_object_t *, char *key, char *string);\nvoid json_put_number(json_t *, json_object_t *, char *key, double number);\nvoid json_put_bool(json_t *, json_object_t *, bool value);\nvoid json_put_null(json_t *, json_object_t *, char *key);\n\n// create a json data type on a json_t memory context\njson_object_t *json_new_object(json_t *);\njson_object_t *json_new_array(json_t *, json_object_t **objects, size_t size);\njson_object_t *json_new_string(json_t *, char *string);\njson_object_t *json_new_number(json_t *, double number);\njson_object_t *json_new_bool(json_t *, bool value);\njson_object_t *json_new_null(json_t *);\n```\n\n## examples\n\n```c\n// load json from a file and print it to stdout with formatting\njson_t json;\njson_load_file(\u0026json, \"data.json\");\n\nchar *str = json_serialize(json.root, false, 2, NULL);\nprintf(str);\nfree(str);\n\njson_unload(\u0026json);\n```\n\n```c\n// load json data into a struct\nchar *json_data =\n\"[{\\\"name\\\": \\\"henry\\\", \\\"age\\\": 21},\"\n\" {\\\"name\\\": \\\"barb\\\", \\\"age\\\": 56}]\";\n\nstruct person { char *name; int age; } people[2];\n\njson_t json;\njson_load(\u0026json, json_data);\n\n// grab array of objects\nsize_t length;\njson_object_t **objects = json_to_array(json.root, \u0026length);\n\n// retrieve object members\nfor (size_t i = 0; i \u003c length; ++i) {\n    people[i].name = strdup(json_get_string(objects[i], \"name\"));\n    people[i].age = (int)json_get_number(objects[i], \"age\");\n}\n\njson_unload(\u0026json);\n```\n\n```c\n// create an empty json document, add data, and save\nconst size_t num_countries = 3;\nstruct country {\n    char *name;\n    int population;\n    bool is_dope;\n} countries[num_countries] = {\n    {\"america\", 3, true},\n    {\"canada\", 10000, true},\n    {\"india\", 56, true}\n};\n\njson_t json;\njson_load_empty(\u0026json);\n\n// add data\njson.root = json_new_object(\u0026json);\n\nfor (size_t i = 0; i \u003c num_countries; ++i) {\n    // create a new country entry\n    json_object_t *country = json_put_object(\n        \u0026json,\n        json.root,\n        countries[i].name\n    );\n\n    // fill in country data\n    json_put_number(\u0026json, country, \"population\", countries[i].population);\n    json_put_bool(\u0026json, country, \"is_dope\", countries[i].is_dope);\n}\n\n// serialize and save to file\nchar *str = json_serialize(json.root, false, 2, NULL);\n\nFILE *file = fopen(\"data.json\", \"w\");\nfprintf(file, str);\nfclose(file);\n\nfree(str);\n\njson_unload(\u0026json);\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarrisonhh%2Fghh_json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgarrisonhh%2Fghh_json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarrisonhh%2Fghh_json/lists"}