Library Architecture
Relevant source files
The following files were used as context for generating this wiki page:
libfastjson is a high-performance C library designed for handling JSON data. It is a fork of the json-c project, optimized for speed and reduced feature set to support essential JSON handling functions in performance-critical environments like rsyslog. The library implements a reference-counting object model that allows for the construction, parsing, and serialization of JSON objects.
Sources: README.md:1-12, README.html:11-15
Core Component Overview
The architecture is centered around several discrete modules that handle object representation, parsing (tokenizing), serialization (printing), and memory management.
| Component | Description | File Reference |
|---|---|---|
| JSON Object Model | Defines the internal representation of JSON types (objects, arrays, strings, etc.) using reference counting. | json_object.h |
| Tokener | A state-machine based parser that converts JSON strings into C object trees. | json_tokener.c |
| Printer | Serializes C object trees back into JSON formatted strings or streams. | json_print.c |
| Printbuf | An optimized, growable string buffer used during serialization and parsing. | printbuf.c |
| Utilities | Helper functions for file I/O and primitive type parsing. | json_util.c |
Sources: json_object.h:46-100, json_tokener.c:215-225, json_print.c:540-560, printbuf.c:38-50
Object Model and Memory Management
The library uses a reference-counting mechanism to manage the lifecycle of fjson_object instances. Objects are created with a reference count of 1. Ownership can be shared via fjson_object_get() and released via fjson_object_put(). When the count reaches zero, the object and its children are recursively freed.
Object Reference Flow
Sources: json_object.h:120-143
Atomic Operations
To support thread-safe reference counting (where configured), the library utilizes atomic builtins. If HAVE_ATOMIC_BUILTINS is defined, it uses GCC builtins like __sync_fetch_and_add. Otherwise, it falls back to pthread mutexes to ensure atomicity during increment and decrement operations.
Sources: atomic.h:37-60
JSON Tokener (Parser)
The fjson_tokener is a state-machine based parser capable of both full and incremental parsing. It maintains a stack to handle nested JSON structures (objects and arrays) up to a configurable maximum depth.
Parsing State Machine
The following diagram illustrates the high-level transition logic within fjson_tokener_parse_ex:
The tokener uses a printbuf to accumulate string literals and handles escape sequences (e.g., \uXXXX, \n, \t) internally.
Sources: json_tokener.c:215-225, json_tokener.c:270-550
Serialization and Printing
The printer module converts fjson_object structures into strings. It supports various formatting flags:
FJSON_TO_STRING_PLAIN: No extra whitespace.FJSON_TO_STRING_SPACED: Minimal whitespace for readability.FJSON_TO_STRING_PRETTY: Full indentation with newlines.
Serialization Flow
The serialization logic uses an internal buffer structure and an overflow callback mechanism to handle large outputs efficiently without excessive memory reallocations.
Data Structures
fjson_object Structure
Internally, the fjson_object is a union that stores data based on the fjson_type.
typedef enum fjson_type {
fjson_type_null,
fjson_type_boolean,
fjson_type_double,
fjson_type_int,
fjson_type_object,
fjson_type_array,
fjson_type_string
} fjson_type;
Sources: json_object.h:103-111
Growable Print Buffer
The printbuf structure is used extensively for string construction. It doubles in size when the current capacity is exceeded to minimize realloc calls.
| Field | Type | Description |
|---|---|---|
buf | char* | The actual character data. |
size | int | Total allocated size of the buffer. |
bpos | int | Current write position (length). |
Sources: printbuf.c:38-50, printbuf.c:65-80
Utility and I/O
The library provides high-level utilities for interacting with the filesystem and parsing primitives from raw strings.
- File I/O:
fjson_object_from_fileandfjson_object_to_filesimplify reading/writing JSON to the disk using file descriptors. - Primitive Parsing:
fjson_parse_int64andfjson_parse_doubleprovide robust parsing of numbers from strings, including workarounds for brokensscanfimplementations in certain environments.
Sources: json_util.c:45-70, json_util.c:166-200
Summary
The libfastjson architecture is designed for efficiency, prioritizing raw performance over strict standard compliance. By utilizing an incremental state-machine parser and an optimized serialization buffer system, it provides a lightweight framework for JSON processing in C. Its reference-counting model ensures predictable memory management suitable for long-running system daemons.