Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 

Repository files navigation

json.h
======

A lightweight, single-header JSON library for C.

Features
--------
- Single-header, header-only design — easy to integrate.
- No external dependencies.
- Simple, intuitive API for working with all JSON types.
- Minimal memory overhead, suitable for embedded or constrained environments.
- Full UTF-8 and UTF-16 support for encoding and decoding.
- Pretty printing for easy debugging.

Usage
-----
Include `json.h` in your project and start working with JSON data.

Supported Types
---------------
Supports JSON types: object, array, string, number, boolean, null.

All types use `struct json_value`.

Parsing and Serialization
-------------------------
/* Parse JSON string into a tree. Supports UTF-8 and UTF-16. */
json_decode(const char *) -> struct json_value *

/* Serialize a JSON tree into a string. Supports UTF-8 and UTF-16. */
json_encode(struct json_value *) -> char *

/* Print JSON to stdout with pretty formatting */
json_print(struct json_value *) -> void

/* Print JSON to stdout with pretty formatting and newline */
json_println(struct json_value *) -> void

Memory Management
-----------------
The `json_free(struct json_value *value)` function is a high-level API that recursively
frees the entire JSON structure, including all child elements. It automatically
handles cleanup based on the value's type, making it the recommended way to free
JSON structures in most cases.

For specialized memory management needs, the following type-specific functions
are still available:

- `json_array_free(struct json_value *array)`:
    Frees the array and recursively frees all of its elements.

- `json_object_free(struct json_value *object)`:
    Frees the object and recursively frees all key-value pairs.

- `json_string_free(struct json_value *string)`:
    Frees the string content and the `struct json_value` itself.

These functions assume ownership of the content they free.
If your program shares ownership or manually manages memory for items
inside arrays, objects, or strings (e.g., for string interning, object pooling,
or custom allocators), you may need to implement custom memory management.

/* Free json value and all its children recursively */
json_free(struct json_value *) -> void

/* Free json value, freeing its children */
json_array_free(struct json_value *) -> void

/* Free json value, freeing its children */
json_object_free(struct json_value *) -> void

/* Free json value and string structure */
json_string_free(struct json_value *) -> void

Some utility functions in this library may automatically allocate, reallocate,
or free memory (e.g., when resizing arrays or adding items to objects).
These behaviors are designed for convenience but may not be suitable for
applications requiring strict memory control.

If you need more control over memory management (e.g., custom allocators,
arena allocation, or memory pooling), this library supports overriding the default
memory allocation functions used throughout the JSON system. By defining the macros listed below
before including the JSON implementation (or via compiler flags), users can inject custom memory
allocators to better suit their application's performance, debugging, or platform-specific needs.

Custom allocator override:
#define JSON_ALLOC(size)         my_malloc(size)
#define JSON_REALLOC(ptr, size)  my_realloc(ptr, size)
#define JSON_FREE(ptr)           my_free(ptr)

Object API
----------
json_object_new() -> struct json_value *
json_object_set(struct json_value *, const char *, struct json_value *) -> void
json_object_get(struct json_value *, const char *) -> struct json_value *
json_object_has(struct json_value *, const char *) -> int
json_object_remove(struct json_value *, const char *) -> void
json_object_clear(struct json_value *) -> void
json_object_iter(struct json_value *, int *iter, char **key, struct json_value **) -> int

Object Macros
-------------
json_is_object(struct json_value *) -> bool
json_object_count(struct json_value *) -> int

Array API
---------
json_array_new() -> struct json_value *
json_array_set(struct json_value *, int, struct json_value *) -> void
json_array_get(struct json_value *, int) -> struct json_value *
json_array_push(struct json_value *, struct json_value *) -> void
json_array_remove(struct json_value *, int) -> void
json_array_clear(struct json_value *) -> void
json_array_iter(struct json_value *, int *iter, struct json_value **) -> int

Array Macros
------------
json_is_array(struct json_value *) -> bool
json_array_count(struct json_value *) -> int

String API
----------
json_string_new(const char *) -> struct json_value *

String Macros
-------------
json_is_string(struct json_value *) -> bool
json_string_set(struct json_value *, const char *) -> void
json_string_get(struct json_value *) -> const char *

Number Macros
-------------
json_is_number(struct json_value *) -> bool
json_number_new(double) -> struct json_value *
json_number_set(struct json_value *, double) -> void
json_number_get(struct json_value *) -> double

Boolean Macros
--------------
json_is_boolean(struct json_value *) -> bool
json_boolean_new(bool) -> struct json_value *
json_boolean_set(struct json_value *, bool) -> void
json_boolean_get(struct json_value *) -> bool

Null Macros
-----------
json_is_null(struct json_value *) -> bool
json_null_new(struct json_value *) -> struct json_value *

Dynamic Memory Management
-------------------------
/* Default initial capacity for arrays (released upon first push) */
#define JSON_ARRAY_INITIAL_CAPACITY 1

/* Growth factor for array capacity (doubles during resizing for now, triggered when the array is full).
Future updates may adjust this to reallocate when 60% of capacity is utilized. */
#define JSON_ARRAY_CAPACITY_MULTIPLIER 2

/* Threshold for array capacity (triggered when the array is full).
Future updates may adjust this to reallocate when 60% of capacity is utilized. */
#define JSON_ARRAY_CAPACITY_THRESHOLD 0.6

/* Default initial capacity for objects (released upon first push) */
#define JSON_OBJECT_INITIAL_CAPACITY 1

/* Growth factor for object capacity, currently doubles during resizing, but future
updates may adjust this to trigger reallocation when 60% of capacity is utilized. */
#define JSON_OBJECT_CAPACITY_MULTIPLIER 2

/* Threshold for object capacity (triggered when the object is full).
Future updates may adjust this to reallocate when 60% of capacity is utilized. */
#define JSON_OBJECT_CAPACITY_THRESHOLD 0.6

Error Handling
--------------
In the event that `json_decode()` fails, the library automatically releases all associated memory
allocations and returns NULL. Error handling can be customized through the following mechanisms:
- Enable built-in error messages by defining `JSON_ERROR`.
- Define a custom error handler by using `JSON_ERROR_HANDLER(CODE, MESSAGE)`.

Embedding
---------
To work with JSON values, declare your root or intermediate node as:
struct json_value *value;

Based on the type stored in value->type, the corresponding data is accessed as follows:
- JSON_TYPE_NULL
  * Represents a null value. No additional data is stored.

- JSON_TYPE_BOOLEAN and JSON_TYPE_NUMBER
  * Access the numeric or boolean data via: `value->number`

- JSON_TYPE_STRING
  * Access the string data via: `value->string`
    Structure definition:
    struct {
        int capacity;  // Allocated size of the string buffer.
        int length;    // Length of the string (excluding null terminator).
        char *value;      // Pointer to the actual string data.
    }

- JSON_TYPE_ARRAY
  * Access the array via: `value->array`
    Structure definition:
    struct {
        int capacity;              // Allocated size of the array (number of elements).
        int length;                // Current number of elements in the array.
        struct json_value **values;   // Pointer to an array of `json_value*`.
    }

- JSON_TYPE_OBJECT
  * Access the object via: `value->object`
    Structure definition:
    struct {
        int capacity;  // Allocated size for key-value pairs.
        int n_items;   // Current number of key-value pairs.
        struct {
            char *key;                 // Pointer to the key string.
            struct json_value *value;  // Pointer to the associated value.
        } **items;                     // Array of key-value pair pointers.
    }

NOTE: To initialize a json_value as an object or array with default values, use the following helper functions:
json_object_init(json_value *value);
json_array_init(json_value *value);

These functions configure internal capacity and structure, preparing the value
for further manipulation (e.g., insertion of elements or key-value pairs).

LICENSE
-------
This software is licensed under the MIT License.
See LICENSE for details.

About

A lightweight, single-header JSON library for C.

Resources

Stars

1 star

Watchers

1 watching

Forks

Contributors

Languages