Primitive Data Types
Relevant source files
The following files were used as context for generating this wiki page:
Primitive data types in libfastjson represent the fundamental building blocks of JSON data structures. These include scalars such as booleans, integers (stored as 64-bit values), doubles, strings, and the null type. The library uses a reference-counting object model, where each primitive is encapsulated within a struct fjson_object that tracks its type and memory lifecycle. Sources: json_object.h:150-160, README.html:16-19
The architecture allows for type coercion, enabling developers to retrieve a value as a different type (e.g., getting an integer from a string representation) while maintaining the internal integrity of the original data. Sources: tests/test_cast.c:1-5, json_object.c:600-610
Core Type Definitions
The library defines seven primary types within the fjson_type enumeration. Primitive types are those that contain leaf values rather than nested containers like objects or arrays.
| Type Constant | Description | Internal Storage |
|---|---|---|
fjson_type_null | Represents a JSON null | N/A (Object pointer is often NULL) |
fjson_type_boolean | Represents true or false | fjson_bool (typedef int) |
fjson_type_double | Double-precision floating point | double (with optional source string) |
fjson_type_int | 64-bit signed integer | int64_t |
fjson_type_string | UTF-8 encoded string | char* (optimized for small strings) |
Sources: json_object.h:173-181, json_object.c:485-500, json_object.c:835-850
Boolean Type
The boolean type handles JSON true and false literals. Internally, it is managed as an integer where 1 represents true and 0 represents false.
Boolean Lifecycle and Parsing
When the tokener encounters "true" or "false", it creates a new boolean object via fjson_object_new_boolean. In strict mode, the tokener only accepts lowercase literals. Sources: json_tokener.c:540-565, json_object.c:575-583
The diagram shows the transition from a JSON literal to the internal representation of a boolean object. Sources: json_tokener.c:540-565
Numerical Types: Integer and Double
libfastjson provides distinct handling for integers and floating-point numbers, though they can often be coerced between one another.
Integer Handling
Integers are stored internally as int64_t to ensure maximum precision for large numbers. The library provides functions to retrieve these as 32-bit or 64-bit signed/unsigned values, with range checks performed for 32-bit targets. Sources: json_object.h:400-440, json_object.c:615-635
Double-Precision Floating Point
The double type supports standard numeric values, as well as special cases like NaN, Infinity, and -Infinity. An optimization exists where the original string representation (source) can be stored to ensure exact re-serialization of values like "12.3" that might otherwise suffer from precision display artifacts (e.g., "12.300000000000001"). Sources: json_object.h:460-475, json_object.c:705-725, json_print.c:300-315
Numeric Parsing Logic
The library utilizes sscanf with specific workarounds for broken implementations to ensure reliable 64-bit integer parsing. Sources: json_util.c:130-180
This flow illustrates the logic used by the tokener to decide whether to treat a numeric literal as an integer or a double. Sources: json_tokener.c:578-620
String Type
Strings are stored as null-terminated character arrays. libfastjson implements a performance optimization for "short" strings to reduce allocation overhead.
- Direct Storage: Very short strings (under
LEN_DIRECT_STRING_DATA) are stored directly within the object structure. - Pointer Storage: Longer strings are allocated on the heap and managed via a pointer.
- Escaping: During serialization, characters such as
\n,\r,\t, and"are escaped using a high-performance lookup tablechar_needsEscape.
Sources: json_object.c:45-120, json_object.c:835-860, json_print.c:205-240
Character Escaping Table
The library uses a 256-byte table to determine if a character requires escaping, providing a performance increase of over 30% during serialization. Sources: json_print.c:190-205, json_object.c:45-80
| Character | Escape Sequence |
|---|---|
" | \" |
\ | \\ |
/ | \/ |
\n | \n |
| Control Chars | \u00xx |
Sources: json_object.c:90-115, json_print.c:215-230
Type Coercion Logic
The fjson_object_get_* functions perform automatic type coercion to facilitate easier data access.
The sequence shows how the library attempts to satisfy a type-specific request even if the underlying object is of a different primitive type. Sources: json_object.c:600-640, tests/test_cast.c:75-90
Summary of Primitive API
| Function | Purpose | Return Type |
|---|---|---|
fjson_object_new_boolean(b) | Creates a boolean object | fjson_object* |
fjson_object_new_int64(i) | Creates a 64-bit integer object | fjson_object* |
fjson_object_new_double(d) | Creates a double object | fjson_object* |
fjson_object_new_string(s) | Creates a string object | fjson_object* |
fjson_object_get_type(obj) | Returns the enum type of the object | fjson_type |
Sources: json_object.h:355-380, json_object.h:460-465, json_object.h:550-560
Primitive types in libfastjson are designed for high-speed processing while maintaining flexibility through coercion and exact numeric representation support. Their lifecycle is managed through a reference-counting system initialized at creation. Sources: README.md:1-10, json_object.c:140-160