nosjob: a C++ library for working with JSON data

Welcome to nosjob, a C++ library for generating and consuming JSON data.

The name "nosjob" (pronounced "nose job") came about one early morning after about 12 hours of hacking. My tired eyes looked on the words "JSON object" and briefly read them as "NOSJ ob..." And so the name was chosen. (There are probably already ten other JSON/C++ toolkits with the name "jsonpp," which was my initial choice of names.)

License: the core code is released into the Public Domain, but the stuff under src/utf8/ and src/parser/ were written by other people and have BSD-like licenses ("do whatever you want with the code, but don't remove the copyright notice").

Supports JSON-compliant numeric, Boolean, Null, String, Object, and Array data. Strings can be UTF-8 or 16-bit UTF-16 (the full range of UTF-16 code points is not supported... at least i don't think so).

Compiles cleanly on 64-bit and 32-bit platforms.

It can handle ASCII or UTF-8, or UTF-16 data. (That said, UTF-16 is only very lightly tested!)

Supports formatted and unformatted JSON output (that is, with or without extra spacing for human-readability).

The data types have full value semantics, and can be copied around cheaply while still internally retaining all type-specific information. This functionality does not use virtual inheritance.

Includes a client-extendable template-based mechanism for converting between the library's data types and native types. e.g. convert from a std::map to an Object or a std::list to an Array, provided the key/value types in the map/list are themselves convertible.

The internally-used page-based allocator has optional support for pthread- or Win32-based mutex locking. Which reminds me...

This code is untested on any non-Linux platforms. "It should work," but i've never tried. It uses only ISO-specified C++ APIs, and ANSI-specified APIs for the C bits, so it should work on any compliant platform.

Primary Misfeatures

Young and experimental. (But what's there seems to work as advertized.)

On 32-bit platforms its Integer type currently only supports 32-bit values. This is on the to-fix list (it's easy enough to do, but i hate the extra allocations). On platforms where sizeof(void*)>=sizeof(int64_t), 64-bit integers are used by default.

The internals of the API are somewhat convoluted as a side-effect of the polymorphic-copying-without-virtual-inheritance mechanism (see AtomInternals).

It models only the data conventions specified by JSON, and not the full range of JavaScript features these types have access to in JS code.

It has to allocate memory quite often (but in small amounts). We use reference counting whereever possible, and a page-based memory pool to try to alleviate memory fragementation, but there is still more work to do here. Some of the more interesting optimizations are hindered by earlier design decisions which need to be worked out. That said, it normally requires relatively little memory at any one time. The test/demo application currently (20101117) has a peak concurrent memory usage of only about 20 kilobytes on 64-bit machines and 16kb on 32-bit. (Large JSON trees will of course require more memory.)

The various "cast" operators above don't really cast anything. They simply copy a couple internal pointers around to upgrade a base Atom object to its full-fledged concrete type. Trying to "cast" to an incompatible type will cause an exception to be thrown.