Library / SDK
akheron/jansson avatar
akheron/jansson

jansson: the C JSON library that wins by having nothing to install

C library for encoding, decoding and manipulating JSON data

3,371 stars856 forksCNOASSERTION

At a glance

What is it?
Two decades of steady maintenance, a reference-counted JSON tree, and a build you can produce from a tarball in three commands. A look at what makes jansson still worth choosing.
Who is it for?
jansson is a good default pick for C and C++ code that needs to read or write JSON and does not want a dependency tree attached to it. The reference-counted tree in src/ handles ownership explicitly, the dump and pack flags give you precise control over output, and the build works from a tarball or a git checkout without a package manager in the middle.
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 92 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 October 9, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A small library whose case rests on what it does not need

The feature list in the README is short enough to read in one pass, and the most interesting items are the absences. Jansson is a C library for encoding, decoding and manipulating JSON data with no dependencies on other libraries, full Unicode support through UTF-8, and what the README calls an extensive test suite. At 3,367 stars and 853 forks it is not a niche utility, and the fork count is a fair signal here because forking a C library is how vendoring usually starts.

The license field on GitHub reads unasserted while the README states plainly that Jansson is under the MIT license and points at the LICENSE file in the source distribution. Both can be true at once: that classifier is often left unset on older C projects even when the license text is unambiguous in the tree. If license clarity matters to your legal review, the LICENSE file is what to read.

The tree is tidy for a project of this age. `src/` holds the library itself, `test/` the suite, `doc/` the Sphinx sources, `examples/` two files that exist to be read, `cmake/` and `configure.ac` the two supported build paths, and then the supporting cast: `release.sh`, `scripts/`, `CONTRIBUTING.md`, `SECURITY.md` and `.github/`. The homepage still points at digip.org, which dates the project's origins, while continuous integration runs on both GitHub Actions and AppVeyor, as the two badges at the top of the README indicate.

Three commands from a tarball, one extra from a git clone

Jansson ships source tarballs on GitHub Releases, and installing one is the standard autotools sequence. The README gives it in four lines:

bash
./configure
make
make install

To run the test suite, the README adds one more:

bash
make check

That is the whole install story, and it is worth contrasting with the usual modern alternative. There is no package manager required, no vendored copy to keep in sync, and no ABI to negotiate beyond the library version you compiled against. For a project that will be linked into a longer-lived binary, building from the tarball gives you a known source revision rather than whatever a distribution decided to ship.

The git checkout path needs one extra step, because `configure` has to be generated before it exists. The README is explicit that autoreconf is the easy way to do it:

bash
autoreconf -i

If your build system is CMake instead, `CMakeLists.txt` and the `cmake/` directory provide the alternative, and the 2.15.0 release notes record the move to target-based CMake settings as a deliberate improvement. Android is a first-class target too, with `Android.mk` and an `android/` directory checked into the tree rather than left to a third-party build script.

Documentation lives in Sphinx, examples live in the repository

The README's documentation section is brief and points at readthedocs for the manual itself. The manual source is in `doc/`, and the README explains how to render it locally. It requires Sphinx 1.0 or newer, and the build output lands somewhere you can open directly:

bash
make html

Then you point a browser at `doc/_build/html/index.html`. This is the part of the project where the split between README and documentation matters most, because Jansson's API surface is large and the README deliberately does not summarize it. The reference manual is where the function-by-function detail lives, including the dump flags, the pack format string, the error codes, and the encoding helpers.

The repository compensates with `examples/`, which contains just two files. `examples/README.rst` frames them, and `examples/simple_parse.c` is the one to read first. A short, complete, compilable parse example teaches more about the ownership model than any amount of prose about reference counting, because you can see where `json_loads` hands you a value and where your program is responsible for decrementing it.

One naming detail worth knowing before you grep the headers: the hashtable implementation is discussed in release notes as `hashtable.h`, so internal headers follow the `jansson_` prefix convention. The 2.15.1 build notes tightened that convention, exporting only symbols beginning with `json_` and `jansson_` from the CMake build, which is a reasonable thing to want from a library that will sit in someone else's symbol table.

Recursion limits and negative lengths define the 2.15.1 release

Version 2.15.1 was published on 2026-07-01, five days before the last push recorded for the default branch, and it reads like a hardening release rather than a feature release. Three fixes stand out. The first includes the object key or array index in unpack type mismatch error messages, which turns a vague failure into one that tells you which member of a document failed to parse.

The second rejects negative string length in the `json_pack` `s#` and `+#` formats. This is the kind of bug that matters more than its severity suggests, because the pack format string is a compact interface where a negative length is exactly the kind of value a careless caller might compute from an untrusted measurement.

The third is the substantive one: recursion depth is now limited in dump, equal and deep copy to prevent stack overflow. Unbounded recursion on attacker-supplied JSON is a denial-of-service vector in any C program, and dumping a deeply nested document is an ordinary operation that any service parsing user input might perform. `SECURITY.md` is present in the tree, which suggests the project takes the reporting path seriously, but the fix landing in a point release rather than a major version is a statement about how the maintainer judged the compatibility cost.

For anyone pinning a version, 2.15.1 is the one to want if your process accepts JSON from anywhere it does not fully control.

The dtoa change altered how real numbers come out

Version 2.14.1, published 2025-03-23, carries the change most likely to alter existing program output. It switched real number formatting to David M. Gay's `dtoa()` algorithm to avoid misprinting issues with values that are not exactly representable as a `double`. In practice this means the shortest decimal string that round-trips to the same binary value is what gets emitted, instead of whatever the previous algorithm produced.

That sounds like a small detail and is not. Any code that hashes a serialized JSON document, compares it byte for byte across systems, or signs it will see different bytes after this release. Code that parses and re-emits configuration will not, because the value survives the round trip either way. If you have golden files containing serialized floats, they are the place this will surface.

The release notes are unusually helpful about opting out, naming both the autotools and CMake switches for disabling the new algorithm. That is a good sign about the maintainer's judgment: a change to output formatting is exactly the kind of thing that should be reversible at build time rather than permanent.

Version 2.15.0, published 2026-01-24, was smaller: it added `json_set_alloc_funcs2` and `json_get_alloc_funcs2` to support realloc-aware allocator hooks, and it optimized serialization. The allocator extension matters for anyone embedding jansson in a process that owns its own memory, since replacing malloc and free wholesale is a blunt instrument when what you actually want is to control growth.

Where jansson fits against the other C JSON options

The honest comparison is not with json-c or cJSON or RapidJSON on features, because all of them parse JSON. It is on what your program has to hold in its head. Jansson hands you a tree of refcounted values with explicit constructors and accessors, so the type system and the naming both tell you what a function does. RapidJSON is faster and more permissive, and its in-place parsing is a genuine advantage on large documents, but it is noticeably easier to misuse.

The tradeoff runs the other way too. Jansson's explicit model means more allocation and more calls than an in-place parser, and it means the same discipline you would apply to any refcounted C API, including the requirement that every value you receive has exactly one matching decrement. For a long-running service, that is a cost that has to be paid once and then followed consistently.

The project is not archived, it has 135 open issues, and the last push to the default branch was 2026-07-09, roughly three months before this article was written. Release cadence over the visible history is a point release every several months, which is the pace you want from a library this heavily embedded: frequent enough to land security fixes like the recursion limits in 2.15.1, slow enough that the API is not moving under you.

If you are evaluating it, the shortest useful path is the tarball install, `make check` to confirm your toolchain, then `examples/simple_parse.c` to see the ownership pattern in twenty lines. The reference manual is where the rest lives, and it is better documented than most C libraries of comparable age.

Editorial conclusion

jansson is a good default pick for C and C++ code that needs to read or write JSON and does not want a dependency tree attached to it. The reference-counted tree in src/ handles ownership explicitly, the dump and pack flags give you precise control over output, and the build works from a tarball or a git checkout without a package manager in the middle. What the README does not settle is anything about thread safety beyond the locale fix in 2.14.1, or how the library behaves on adversarial input beyond the depth limits added in 2.15.1. The last push was 2026-07-09, five days before the 2.15.1 release. Start by reading doc/apiref.rst in the published documentation and examples/simple_parse.c in the repository, then decide whether the reference-counted model fits the way your code already handles ownership.

Frequently asked questions

Is jansson still actively maintained?

The repository is not archived and the last push to the default branch was 2026-07-09. Releases are point releases on a cadence of a few months, with v2.15.1 published on 2026-07-01 and v2.15.0 on 2026-01-24. There are 135 open issues, so maintenance is active rather than a holding pattern.

Does jansson require any other libraries to build?

No. The README lists no dependencies on other libraries as one of the design principles, and building from a release tarball is just configure, make and make install. From a git checkout you run autoreconf first to generate the configure script. CMake is supported as an alternative build path.

How does jansson handle deeply nested or malformed JSON?

Since v2.15.1, published 2026-07-01, recursion depth is limited in dump, equal and deep copy to prevent stack overflow on hostile input. The same release rejects negative string lengths in the json_pack format string, and earlier ones added the object key or array index to unpack type mismatch messages so a parse failure points at the offending member.

Official sources

  1. akheron/jansson on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/akheron-jansson.svg)](https://hysenlabs.com/projects/akheron-jansson)