Introduction to libfastjson
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, specifically optimized for speed and a reduced memory footprint. The primary goal of the project is to provide essential JSON handling functions while maintaining a small library size and maximizing processing speed, even if it means sacrificing 100% standards compliance.
Sources: README.md:1-12, README.html:10-14
Core Architecture and Object Model
libfastjson implements a reference-counting object model. This allows developers to construct JSON objects in C, serialize them into formatted strings, and parse JSON strings back into C representations. The library manages memory automatically through these reference counts, freeing objects only when their count reaches zero.
Sources: README.html:10-14, json_object.c:148-164
Supported Data Types
The library supports seven primary JSON types, managed through the fjson_type enumeration:
| Type Constant | Description |
|---|---|
fjson_type_null | Represents a null value or a NULL object. |
fjson_type_boolean | Represents boolean true/false values. |
fjson_type_double | Represents floating-point numbers. |
fjson_type_int | Represents 64-bit integer values. |
fjson_type_object | Represents a JSON object (key-value pairs). |
fjson_type_array | Represents a JSON array (ordered list). |
fjson_type_string | Represents a UTF-8 encoded string. |
Sources: json_object.h:130-140, json_object.c:204-215
Reference Counting Logic
Memory management is handled by two primary functions: fjson_object_get() and fjson_object_put(). The logic ensures that shared ownership is possible until the last owner releases the object.
Sources: json_object.h:147-161, json_object.c:148-164
JSON Parsing (Tokener)
The fjson_tokener is the core component responsible for converting strings into fjson_object trees. It supports both simple parsing of complete strings and incremental parsing for large data streams.
Parsing States
The tokener operates as a state machine. It transitions through various states such as eatws (eat whitespace), start, string, number, and array as it consumes characters.
Sources: json_tokener.c:237-640
Key Parsing Functions
| Function | Purpose |
|---|---|
fjson_tokener_parse | Parses a null-terminated string into an object. |
fjson_tokener_parse_ex | Advanced parser supporting incremental data and length limits. |
fjson_tokener_new | Allocates a new tokener instance for stateful parsing. |
fjson_tokener_reset | Resets the tokener state for a new parsing task. |
Sources: json_tokener.c:140-190, json_tokener.c:215-225
Serialization and Printing
libfastjson provides multiple ways to "stringify" JSON objects. It includes optimizations for performance, such as a lookup table (char_needsEscape) to quickly identify characters requiring escaping.
Sources: json_print.c:205-220, json_object.c:64-106
Output Flags
When converting objects to strings using fjson_object_to_json_string_ext(), several flags control the output format:
FJSON_TO_STRING_PLAIN: No extra whitespace.FJSON_TO_STRING_SPACED: Adds minimal spaces for readability.FJSON_TO_STRING_PRETTY: Full indentation with newlines.FJSON_TO_STRING_NOZERO: Drops trailing zeros in floating-point numbers.
Sources: json_object.h:46-77
Internal Buffering
The library uses a printbuf structure to manage dynamic string growth during serialization. This reduces the number of small memory allocations by growing the buffer exponentially as needed.
Sources: printbuf.c:38-100, json_object.c:221-236
Utility and File I/O
The library includes high-level utility functions in json_util.c for interacting with the filesystem and parsing primitive types directly.
- File Reading:
fjson_object_from_file(const char *filename)opens a file and parses its contents into a JSON object tree. - File Writing:
fjson_object_to_file(const char *filename, struct fjson_object *obj)serializes an object and saves it to disk. - Safe Parsing:
fjson_parse_int64andfjson_parse_doubleprovide robust string-to-number conversion, including workarounds for brokensscanfimplementations on certain platforms.
Sources: json_util.c:65-98, json_util.c:134-142, json_util.c:166-260
Conclusion
libfastjson serves as a high-performance alternative to json-c, focusing on the needs of applications requiring rapid JSON processing like rsyslog. By utilizing an efficient reference-counting model, a state-machine-based tokener, and optimized serialization paths, it provides a balance between functionality and extreme speed.
Sources: README.md:1-12, json_object.c:64-80