cerialize is a lightweight, single-header JSON deserializer written in C. It provides a simple API for parsing JSON strings into C data structures, with robust error handling and support for core JSON types.
- Single-header library: Just include
cerialize.hin your project. - Supports core JSON types: Object, String, Number, Boolean, Null, List (Array).
- Strict error handling: Detailed error messages for invalid input.
- Test suite included: Comprehensive tests for all supported types.
Copy include/cerialize/cerialize.h into your project, or reference it directly.
#include "cerialize/cerialize.h"const char* json_str = "{\"key\": \"value\", \"num\": 42, \"flag\": true, \"missing\": null}";
json result = deserialize_json(json_str, strlen(json_str));
if (result.failure) {
printf("Parse error: %s\n", result.error_text);
json_free(&result); // Clean up even on failure
return 1;
} else {
// Access result.root (json_object)
// See Data Types section below
}
// Always free memory when done
json_free(&result);- json_type: Enum for type discrimination.
JSON_OBJECT,JSON_STRING,JSON_NUMBER,JSON_BOOL,JSON_NULL,JSON_LIST
- json_value: Union holding the actual value.
string:char*number:floatboolean:bool_t(char, TRUE/FALSE)is_null:bool_tnodes: Array ofjson_node(for objects and lists)node_count: Number of nodes (for objects and lists)
- json_node: Represents a key-value pair in an object, or an element in a list.
- For objects:
keyis set,valueis the value. - For lists:
keyis NULL,valueis the element value.
- For objects:
- json_object: Main parsed value.
type:json_typevalue:json_value
- json: Top-level result.
root:json_objecterror_text: Error message (if any)failure: TRUE if parsing failed
if (result.root.type == JSON_OBJECT) {
for (cereal_size_t i = 0; i < result.root.value.node_count; ++i) {
json_node node = result.root.value.nodes[i];
printf("Key: %s\n", node.key);
// Check node.value type and access accordingly
}
}if (result.root.type == JSON_LIST) {
for (cereal_size_t i = 0; i < result.root.value.node_count; ++i) {
json_node node = result.root.value.nodes[i];
// node.key will be NULL
// node.value holds the element value
}
}Use CMake to build the test suite:
rm -rf build
mkdir -p build
cd build
cmake ..
make
cd ..This will compile the test suite and place the binary in build/tests.
You can run the tests using the provided script:
./run_tests.shOr, run the test binary directly after building:
./build/testsYou can also compile manually:
gcc -std=c99 -Wall -Wextra -Iinclude -Itest/helpers -Itest/cases -o build/tests test/tests.c test/helpers/test_output_helper.c -g
./build/tests- test/cases/: Individual test files for each data type.
- test/helpers/: Utility functions for testing.
- test/tests.c: Main test runner.
- String: Must be enclosed in single quotes (
\"example\"). Newlines inside strings are not allowed. - Number: Supports integers, floats, and exponents. Strict format checking.
- Boolean: Only accepts
trueorfalse(case-sensitive).1and0are rejected. - Null: Only accepts
null(case-sensitive). - Object: Key-value pairs, keys must be strings.
- List (Array): Elements separated by commas, supports mixed types. Trailing commas are allowed and ignored. Empty lists are supported.
Important: Always call json_free() to prevent memory leaks.
json_free(json* j): Frees all memory associated with a JSON structurejson_object_free(json_object* obj): Frees memory for individual JSON objects (used internally)
- Recursive cleanup: Automatically frees nested objects, arrays, and strings
- NULL safety: Safe to call on NULL pointers
- Double-free protection: Safe to call multiple times on the same structure
- Complete reset: Resets the structure after freeing
json result = deserialize_json(json_string, strlen(json_string));
// Use the result...
json_free(&result); // Always free when donejson result = deserialize_json(json_string, strlen(json_string));
if (result.failure) {
printf("Error: %s\n", result.error_text);
json_free(&result); // Free even on failure
return 1;
}
// Normal processing...
json_free(&result);// Even deeply nested structures are cleaned up with one call
const char* complex = "{\"users\":[{\"name\":\"John\",\"data\":{\"age\":30}}]}";
json result = deserialize_json(complex, strlen(complex));
// Use the result...
json_free(&result); // Frees everything recursivelyAll parsing errors are reported via the error_text field in the json struct. Common errors include:
- Missing or mismatched quotes
- Invalid number format
- Unexpected characters
- Multiple values where only one is allowed
- Add new tests in
test/cases/ - Use the provided helpers for assertions
- Document new features and types
This project is licensed under the MIT License. You are free to use, modify, and distribute this software with attribution. See the LICENSE file for full details.
For more details, see the code in include/cerialize/cerialize.h and the test suite in test/.