json-c: A Reference-Counted JSON Library for C
https://github.com/json-c/json-c is the official code repository for json-c. See the wiki for release tarballs for download. API docs at http://json-c.github.io/json-c/
At a glance
- What is it?
- json-c parses and emits RFC 8259 JSON through a reference-counted object tree built in C. It suits systems and embedded work where a C ABI and a small dependency footprint matter more than ergonomics.
- Who is it for?
- Adopt json-c when your program is already C or C++ and you want JSON without a C++ runtime, a GC, or a large dependency graph. Do not adopt it if you need schema validation, streaming parsers over huge inputs, or a documented thread-safety guarantee for shared object trees; the README states the opposite for that last point.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 27, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap json-c fills: JSON in C without a C++ runtime
Most JSON libraries assume a managed runtime or a C++ toolchain. json-c assumes neither. It is a C library that implements a reference counting object model, so you construct JSON objects in C, serialize them to strings, and parse strings back into the same in-memory representation. The stated target is RFC 8259 conformance.
The audience is narrow and specific: daemon authors, firmware and embedded developers, and maintainers of C codebases that need to read a config file or emit a structured response without pulling in a C++ standard library. If you are writing C++ and can use a header-only library, json-c is probably not the shortest path. If your build system is CMake and your ABI must stay C, it fits.
One thing to know up front: the repository's license field is reported as NOASSERTION, so the machine-readable metadata does not tell you the terms. The COPYING file is in the repository root, and that is what you should read before shipping.
Reference counting, the tokener, and what the repository layout implies
The mechanism is visible in the file names at the top level. json_object.c and json_object.h hold the object model and the refcount calls. json_tokener.c and json_tokener.h hold the incremental parser that turns text into objects. json_pointer.c implements JSON Pointer, and json_patch.c implements JSON Patch on top of it. json_util.c provides the file and string helpers. arraylist.c is the internal container the library uses for arrays.
The reference counting contract is the part that shapes your code. Every object you obtain is owned by a count, and json_object_put() decrements it. The README describes json_object_get() and json_object_put() as the pair that manages that count, and notes that when threading support is enabled these become atomic operations. That is a deliberate trade: correctness under concurrent refcount traffic in exchange for a documented slowdown. The README cites a figure of at least 3x slower for that path and disables it by default, so the safe default is also the fast default, and the burden of opting in is on you.
Thread safety stops at the refcount. The README is explicit that json-c does not support fully multi-threaded access to object trees. Two threads sharing one parsed object tree and mutating it is outside what the library promises. That constraint is easy to miss because the threading option exists at all.
Build-time feature pruning is another architectural choice. DISABLE_JSON_POINTER removes JSON Pointer support entirely, which matters on constrained targets where the extra code is not worth carrying. DISABLE_THREAD_LOCAL_STORAGE and DISABLE_EXTRA_LIBS exist for the same reason. The library is designed to be cut down.
Installing json-c on Linux and parsing your first document
The README's Unix path uses git, a C compiler, and CMake, with cmake>=2.8 required and 3.16 recommended. On a Debian or Ubuntu system the prerequisites install through the package manager.
sudo apt install git
sudo apt install cmake
sudo apt install doxygen # optional
sudo apt install valgrind # optionalClone the repository and build out of tree. The README notes that a separate build directory is the recommended arrangement and that skipping it can break things such as make distcheck.
git clone https://github.com/json-c/json-c.git
mkdir json-c-build
cd json-c-build
cmake ../json-c
make
make test
sudo make installThe make test step runs the suite and uses valgrind by default; the README gives make USE_VALGRIND=0 test to skip it. To build a static library only, pass the option on the CMake command line.
cmake -DBUILD_SHARED_LIBS=OFF ..After installing, link against libjson-c. The README points to a Linking to libjson-c section for that step, and the repository ships json-c.pc.in, so a pkg-config file is generated by the build. From there, include json.h in your source and use the object and tokener APIs. The README directs new users to the Using json-c section and to the generated API docs at json-c.github.io/json-c for the call-level detail. If you want the documentation built locally, the build directory supports make doc, which produces doc/html/index.html.
Where json-c is the wrong tool
The README's own wording is the clearest limitation: json-c does not support fully multi-threaded access to object trees. Enabling ENABLE_THREADING makes the refcount atomic, not the tree. A design in which several threads walk and modify one shared json_object is not covered by the library, and the option name can create the impression that it is.
Performance is the second boundary. The README cites at least 3x slower for the atomic refcount path, so if your workload is dominated by refcount churn across threads, enabling threading may cost more than the contention it removes. There is no benchmark table in the README to size that against your own code.
There is also no schema validation and no JSON Schema support anywhere in the file listing or the README. json-c validates syntax, not shape. If you need to reject documents that do not match a contract, that check is yours to write.
Finally, the CMake variable table contains a documentation defect worth flagging: DISABLE_STATIC_FPIC and BUILD_STATIC_LIBS are both described as producing a shared library only, which reads as a copy-paste error. Treat that table as a starting point and confirm the actual flag behavior against CMakeLists.txt before relying on it.
json-c versus cJSON and Jansson
cJSON is the usual first stop for C developers because it is a pair of files you can drop into a tree and compile with your project. The difference is in what you get beyond parsing. json-c ships JSON Pointer and JSON Patch implementations in json_pointer.c and json_patch.c, a versioned CMake build with a generated pkg-config file, a documented set of build-time feature switches, and an ABI symbol list in json-c.sym. cJSON's approach is minimalism: fewer moving parts, less to configure, and correspondingly less in the box. If you need to apply a patch document to a parsed tree, json-c has that and cJSON's file set does not.
Jansson is the closer comparison, since it is also a C library with a reference-counted object model. The practical difference is in the build and feature surface rather than the programming model. json-c exposes CMake options for static-only builds, disabling JSON Pointer, disabling thread-local storage, and overriding the random seed function on embedded platforms where even a time() fallback is unavailable. That last option, OVERRIDE_GET_RANDOM_SEED, is aimed squarely at constrained targets. If your platform is a normal Linux or BSD host, the two are closer than the marketing around either suggests, and the deciding factor is likely which one your distribution already packages.
Maintenance, upgrades, and the license question
The last push to the repository was on 2026-09-20, four days before the date of this article, and the repository is not archived. The most recent release listed is json-c 0.19, tagged json-c-0.19-20260627 on 2026-06-27. So the project is being touched and releases are being cut, but the release cadence is not something the README states, and you should not read a push date as a support commitment.
Upgrade cost is dominated by the ABI. The repository includes json-c.sym, a symbol list, and abi-check.sh, a script whose presence indicates ABI compatibility is tracked deliberately between versions. For a shared-library deployment that is the number to watch: if a symbol disappears or changes, everything linked against libjson-c needs a rebuild, not just a relink. The repository also carries per-release notes in files such as issues_closed_for_0.19.md, which is where the actual behavior changes for a given version are recorded.
On licensing, the machine-readable metadata says NOASSERTION, which is not a license. The COPYING file in the repository root is the authoritative text, and if you are redistributing libjson-c in a product, that file is what your review should be based on. This is not legal advice; it is an observation that the metadata alone will not answer the question.
Editorial conclusion
Adopt json-c when your program is already C or C++ and you want JSON without a C++ runtime, a GC, or a large dependency graph. Do not adopt it if you need schema validation, streaming parsers over huge inputs, or a documented thread-safety guarantee for shared object trees; the README states the opposite for that last point. Before committing, build the 0.19 tag with -DBUILD_SHARED_LIBS=OFF for your target, then confirm whether you need -DENABLE_THREADING=ON, because the README notes the atomic operations it adds can cost at least 3x in that path.
Frequently asked questions
What is json-c?
json-c is a JSON implementation in C that uses a reference counting object model, letting you construct JSON objects, serialize them to strings, and parse strings back into objects. It aims to conform to RFC 8259.
How do I install json-c?
On Unix, clone the repository, create a build directory, and run cmake ../json-c followed by make, make test, and sudo make install. The README also documents a vcpkg path and a cmake-configure wrapper for those used to autoconf.
What is the difference between json-c and cJSON?
Both are C JSON libraries, but json-c ships JSON Pointer and JSON Patch implementations and a CMake build with documented feature switches, while cJSON's approach is a minimal drop-in file set. The README does not compare the two directly.
Is json-c thread safe?
Not for shared object trees. The README states that json-c does not support fully multi-threaded access to object trees; ENABLE_THREADING only makes json_object_get() and json_object_put() atomic, and the README notes that can be at least 3x slower.
Where can I find json-c documentation?
API docs are hosted at json-c.github.io/json-c, and the project wiki is the home page linked from the README. You can also build the docs locally with make doc in the build directory, which produces doc/html/index.html.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/json-c-json-c)