AxlJson — JSON

See AxlData — Data Structures for an overview of all data modules including JSON parsing and building.

Header: <axl/axl-json.h>

API Reference

Defines

AXL_JSON_WRITER_MAX_DEPTH

Maximum nesting depth the writer’s state machine tracks.

Enums

enum AxlJsonParserFlags

AxlJsonParserFlags:

Flags passed to axl_json_parse_flags. The default (0) is strict RFC 8259 JSON, exactly what axl_json_parse accepts.

Values:

enumerator AXL_JSON_PARSER_DEFAULT

strict RFC 8259 (default)

enumerator AXL_JSON_PARSER_JSON5

json5.org grammar superset

enum AxlJsonWriterFlags

AxlJsonWriterFlags:

Flags passed to axl_json_writer_init.

Values:

enumerator AXL_JSON_WRITER_DEFAULT

compact output, strict JSON

enumerator AXL_JSON_WRITER_PRETTY

2-space indent + newlines

enumerator AXL_JSON_WRITER_TRAILING_COMMAS

emit JSON5-style trailing commas

Functions

bool axl_json_parse(const char *json, size_t len, AxlJsonReader *r)

Parse a JSON string.

Allocates a token array sized to fit the document. Call axl_json_free() when done to release the token memory.

Parameters:
  • json – JSON string (NUL terminator not required)

  • len – length of json in bytes

  • r – reader to fill

Returns:

true on success, false on parse error or allocation failure.

bool axl_json_parse_flags(const char *json, size_t len, uint32_t flags, AxlJsonReader *r)

Parse a JSON or JSON5 string.

Identical to axl_json_parse but accepts a flags bitmask. Pass AXL_JSON_PARSER_JSON5 to accept the JSON5 grammar superset: line comments (//) and block comments, trailing commas, single-quoted strings, unquoted (identifier-name) object keys, hex number literals, and the JSON5 string-escape set (\x##, \v, \0, line continuations).

The resulting reader is consumed by the same accessors (axl_json_get_string etc.) as a strict-JSON reader — JSON5 features are normalized at parse time.

Parameters:
  • json – JSON / JSON5 string

  • len – length in bytes

  • flags – AxlJsonParserFlags bitmask

  • r – reader to fill

Returns:

true on success, false on parse error or allocation failure.

void axl_json_free(AxlJsonReader *r)

Free a parsed JSON reader.

Releases the heap-allocated token array. Safe to call on readers that don’t own their tokens (e.g. array elements). NULL-safe.

Parameters:
  • r – reader to free (NULL-safe)

bool axl_json_load_file(const char *path, AxlJsonReader *r, void **out_buf, size_t *out_len)

One-shot: read a file, parse it as JSON.

Convenience wrapper around axl_file_get_contents + axl_json_parse. The reader references the loaded buffer — the caller must keep *out_buf alive for the lifetime of r and free it (via axl_free) after calling axl_json_free on r.

Typical use:

AxlJsonReader r = { 0 };
void   *raw = NULL;
size_t  raw_len = 0;
if (axl_json_load_file("config.json", &r, &raw, &raw_len)) {
    axl_json_get_string(&r, "name", name, sizeof(name));
    // ...
    axl_json_free(&r);
    axl_free(raw);
}

On failure (file unreadable, parse error, OOM) returns false and leaves r untouched, sets *out_buf to NULL, and frees any intermediate allocation.

Parameters:
  • path – file path (UTF-8)

  • r – [out] reader to fill

  • out_buf – [out] file contents (caller frees)

  • out_len – [out, optional] file size in bytes

Returns:

true on success, false otherwise.

bool axl_json_load_file_flags(const char *path, uint32_t flags, AxlJsonReader *r, void **out_buf, size_t *out_len)

One-shot: read a file, parse it as JSON or JSON5.

Identical to axl_json_load_file but accepts a flags bitmask forwarded to axl_json_parse_flags. Use this for sidecar config files that want comments, trailing commas, etc.

Parameters:
  • path – file path (UTF-8)

  • flags – AxlJsonParserFlags bitmask

  • r – [out] reader to fill

  • out_buf – [out] file contents (caller frees)

  • out_len – [out, optional] file size in bytes

Returns:

true on success, false otherwise.

bool axl_json_get_string(const AxlJsonReader *r, const char *key, char *value, size_t value_size)

Extract a string value from a parsed JSON object.

Parameters:
  • r – reader

  • key – key to look up

  • value – buffer for string value

  • value_size – size of value buffer

Returns:

true if found, false if not found or not a string.

bool axl_json_get_int(const AxlJsonReader *r, const char *key, int64_t *value)

Extract an integer value from a parsed JSON object.

Parameters:
  • r – reader

  • key – key to look up

  • value – receives the integer

Returns:

true if found, false if not found or not a number.

bool axl_json_get_uint(const AxlJsonReader *r, const char *key, uint64_t *value)

Extract an unsigned integer value from a parsed JSON object.

Parameters:
  • r – reader

  • key – key to look up

  • value – receives the unsigned integer

Returns:

true if found, false if not found or not a number.

bool axl_json_get_bool(const AxlJsonReader *r, const char *key, bool *value)

Extract a boolean value from a parsed JSON object.

Parameters:
  • r – reader

  • key – key to look up

  • value – receives the boolean

Returns:

true if found, false if not found or not a boolean.

bool axl_json_extract_string(const char *json, size_t len, const char *key, char *value, size_t value_size)

One-shot: parse + extract a string in one call.

Handles allocation and cleanup internally.

Parameters:
  • json – JSON string

  • len – length

  • key – key to extract

  • value – buffer for value

  • value_size – buffer size

Returns:

true on success.

bool axl_json_array_begin(const AxlJsonReader *r, const char *key, AxlJsonArrayIter *iter)

Begin iterating a JSON array value by key name.

Parameters:
  • r – reader

  • key – key of the array field

  • iter – iterator to initialize

Returns:

true if array found, false if not found or not an array.

bool axl_json_root_array_begin(const AxlJsonReader *r, AxlJsonArrayIter *iter)

Begin iterating a root-level JSON array.

Use when the JSON document is a bare array: [{...}, {...}, ...] rather than an object with a named array field.

Parameters:
  • r – reader

  • iter – iterator to initialize

Returns:

true if root is an array, false otherwise.

bool axl_json_array_next(AxlJsonArrayIter *iter, AxlJsonReader *element)

Advance to the next array element.

The element reader borrows the parent’s token array — do not call axl_json_free on it. It remains valid until the parent reader is freed.

Parameters:
  • iter – iterator

  • element – reader for the element

Returns:

true if element returned, false if no more elements.

int axl_json_escape_string(const char *src, char *out, size_t size)

Escape a string for safe embedding in JSON.

Writes the escaped string WITH surrounding double quotes into out. Escapes double-quote, backslash, the standard whitespace escapes (newline / carriage-return / tab), and any remaining control characters below 0x20.

Parameters:
  • src – input string (UTF-8)

  • out – output buffer

  • size – output buffer size

Returns:

number of bytes written (excluding NUL), or -1 on error or truncation.

void axl_json_writer_init(AxlJsonWriter *w, AxlString *out, uint32_t flags)

Initialize a writer.

The writer appends to the AxlString — it does not clear it. To reuse a string between writes, the caller calls axl_string_clear() before init.

Parameters:
  • w – writer to initialize

  • out – destination string (caller-owned)

  • flags – AxlJsonWriterFlags

size_t axl_json_writer_finish(AxlJsonWriter *w)

Finalize the writer.

Validates that all opened containers were closed; sets the sticky error flag if not.

Parameters:
  • w – writer

Returns:

total number of bytes written into out by this writer.

bool axl_json_writer_error(const AxlJsonWriter *w)

Query the sticky error flag.

Set on AxlString OOM or structural misuse (see README). Once set, all subsequent writer calls become no-ops.

Parameters:
  • w – writer

Returns:

true if any error occurred since init.

void axl_json_obj_begin(AxlJsonWriter *w)

Open an object ({).

Parameters:
  • w – writer

void axl_json_obj_end(AxlJsonWriter *w)

Close the current object (}).

Parameters:
  • w – writer

void axl_json_arr_begin(AxlJsonWriter *w)

Open an array ([).

Parameters:
  • w – writer

void axl_json_arr_end(AxlJsonWriter *w)

Close the current array (]).

Parameters:
  • w – writer

void axl_json_key(AxlJsonWriter *w, const char *key)

Emit a key ("key":). Must be inside an object context.

Parameters:
  • w – writer

  • key – object key (escaped, NUL-terminated)

void axl_json_keyn(AxlJsonWriter *w, const char *key, size_t n)

Emit a key from a non-NUL-terminated buffer ("key":).

Parameters:
  • w – writer

  • key – object key bytes (escaped)

  • n – number of bytes

void axl_json_str(AxlJsonWriter *w, const char *s)

Emit a string atom (escaped).

Parameters:
  • w – writer

  • s – string value (NUL-terminated)

void axl_json_strn(AxlJsonWriter *w, const char *s, size_t n)

Emit a string atom from a non-NUL-terminated buffer (escaped).

Parameters:
  • w – writer

  • s – string bytes

  • n – number of bytes

void axl_json_int(AxlJsonWriter *w, int64_t v)

Emit a signed integer atom.

Parameters:
  • w – writer

  • v – value

void axl_json_uint(AxlJsonWriter *w, uint64_t v)

Emit an unsigned integer atom.

Parameters:
  • w – writer

  • v – value

void axl_json_bool(AxlJsonWriter *w, bool v)

Emit a boolean atom.

Parameters:
  • w – writer

  • v – value

void axl_json_null(AxlJsonWriter *w)

Emit a null atom.

Parameters:
  • w – writer

void axl_json_hex(AxlJsonWriter *w, uint64_t v)

Emit a hex-formatted string atom ("0x1A2B").

Parameters:
  • w – writer

  • v – value

void axl_json_raw(AxlJsonWriter *w, const char *fragment)

Splice a raw JSON fragment into the output (no escaping).

The caller asserts that fragment is well-formed JSON. The writer splices it as-is, just like an atom (handles comma placement and indentation around it).

Parameters:
  • w – writer

  • fragment – pre-formed JSON

void axl_json_comment(AxlJsonWriter *w, const char *text)

Emit a JSON5 comment.

Pretty mode emits // text on its own line at the current indent; compact mode emits / * text * /. Embedded newlines and (in compact mode) close-comment sequences in text are sanitized so the comment can’t break out of its delimiters. The output is only valid JSON5 — strict-JSON parsers will reject it.

Comments don’t disturb the writer’s container state: callers can interleave comments freely between values, between key+value pairs, or as the first/last item in a container.

Parameters:
  • w – writer

  • text – comment text (NUL-terminated, no markup needed)

void axl_json_kv_str(AxlJsonWriter *w, const char *key, const char *value)

"key":"value" — string.

void axl_json_kv_strn(AxlJsonWriter *w, const char *key, const char *value, size_t value_n)

"key":"value" — string from a non-NUL-terminated buffer.

void axl_json_kv_int(AxlJsonWriter *w, const char *key, int64_t value)

"key":<int> — signed integer.

void axl_json_kv_uint(AxlJsonWriter *w, const char *key, uint64_t value)

"key":<uint> — unsigned integer.

void axl_json_kv_bool(AxlJsonWriter *w, const char *key, bool value)

"key":true|false — boolean.

void axl_json_kv_null(AxlJsonWriter *w, const char *key)

"key":null — null.

void axl_json_kv_hex(AxlJsonWriter *w, const char *key, uint64_t value)

"key":"0x1A2B" — hex-formatted string.

void axl_json_write_token(AxlJsonWriter *w, const AxlJsonReader *r, int tok_idx)

Splice an already-parsed token into the writer’s output.

Walks the token tree at tok_idx (objects, arrays, atoms), re-escaping strings as necessary, and emits a faithful copy into the writer. Use to round-trip parts of a parsed document into a larger output without manual re-formatting.

Pass tok_idx = 0 to splice the root document.

Parameters:
  • w – writer

  • r – source reader

  • tok_idx – token index in r (0 = root)

void axl_json_console_print(const char *json, size_t len)

Pretty-print JSON to the console with colors and indentation.

Colors: cyan keys, green strings, yellow numbers, magenta booleans. Distinct from the writer’s AXL_JSON_WRITER_PRETTY flag — that produces buffer output without color; this writes directly to the UEFI console using the platform’s attribute-based color API.

Parameters:
  • json – JSON string (ASCII)

  • len – length in bytes

struct AxlJsonReader
#include <axl-json.h>

axl-json.h:

JSON / JSON5 reader and JSON writer (AxlString-backed). The strict reader parses RFC 8259 JSON via jsmn; an opt-in JSON5 backend (json5.org grammar superset) is reachable through axl_json_parse_flags. The writer builds JSON into an auto-growing AxlString with orthogonal container/key/atom calls, optional 2-space-indent pretty-print mode, and (opt-in) JSON5 trailing-commas + comment emission. A separate colored UEFI-console pretty-printer is provided for debug output.

Three independent APIs:

  • AxlJsonReader — parse + query (strict JSON or JSON5)

  • AxlJsonWriter — build into an AxlString (JSON, optionally JSON5-flavored)

  • axl_json_console_print — colored console output for already-built JSON AxlJsonReader:

Parsed JSON reader. The token array is heap-allocated by axl_json_parse and freed by axl_json_free. References the original JSON buffer (do not free it while using the reader).

Fields are considered private; treat as opaque.

Public Members

const char *json
size_t json_len
int32_t *tokens
int32_t token_count
bool owns_tokens
struct AxlJsonArrayIter
#include <axl-json.h>

AxlJsonArrayIter:

Iterator for JSON arrays. Fields are private.

Public Members

const AxlJsonReader *reader
int32_t array_idx
int32_t pos
int32_t remaining
struct AxlJsonWriter
#include <axl-json.h>

AxlJsonWriter:

Streaming JSON writer that builds into a caller-owned AxlString. Containers, keys, and atoms are independent calls; the state machine handles comma placement, indentation, and the object-vs-array distinction. Fields are private — use accessors.

Public Members

AxlString *out

backing store (caller-owned)

uint32_t flags

AxlJsonWriterFlags.

uint32_t depth

current nesting depth

uint32_t in_array_bits

bit n: depth-n container is array

bool needs_comma

previous emit needs a trailing comma

bool expecting_value

object: true after a key

bool error

sticky error flag

bool last_was_comment

suppress redundant comma + dedent gating