yyjson Usage Guide
SkillDev toolsHigh-performance C JSON parsing, creation, and modification with yyjson.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the yyjson Usage Guide skill
What this skill tells your AI
The instructions your AI receives, as published by luisagroup/luisacompute in .agents/skills/yyjson/SKILL.md and read by ahel’s review.
Single-header ANSI C (yyjson.h + yyjson.c). Two data models: immutable (yyjson_doc/yyjson_val) and mutable (yyjson_mut_doc/yyjson_mut_val). Free the doc to free all values. Arrays/objects are linked lists; index/key lookup is O(n) — prefer iterators.
Project Notes
- The bundled copy is in
src/ext/yyjson(currently 0.12.0). The build optionlc_yyjson_use_xreposwitches to the xmake-repo package. - Luisa code commonly supplies a custom
yyjson_alcthat forwards toluisa::detail::allocator_allocate/reallocate/deallocatewith 16-byte alignment. yyjson_write()/yyjson_mut_write()/yyjson_val_write()allocate their output string with the default allocator. Use the_optsvariants and pass an allocator if the output must use the same allocator as the document.- The bundled target compiles
yyjson.cwith/utf-8on MSVC.
Read JSON
yyjson_doc *doc = yyjson_read(json, len, 0);
yyjson_doc *doc = yyjson_read_file("path", 0, NULL, &err);
yyjson_doc *doc = yyjson_read_opts((char*)dat, len, flg, alc, &err);
yyjson_doc *doc = yyjson_read_fp(fp, flg, alc, &err);
// Incremental
yyjson_incr_state *s = yyjson_incr_new(buf, len, flg, alc);
yyjson_doc *doc = yyjson_incr_read(s, read_len, &err);
yyjson_incr_free(s);
Read flags: YYJSON_READ_NOFLAG (RFC 8259), ALLOW_COMMENTS, ALLOW_TRAILING_COMMAS, ALLOW_INF_AND_NAN, ALLOW_INVALID_UNICODE, NUMBER_AS_RAW, BIGNUM_AS_RAW (overridden by NUMBER_AS_RAW), ALLOW_BOM, ALLOW_EXT_NUMBER, ALLOW_EXT_ESCAPE, ALLOW_EXT_WHITESPACE, ALLOW_SINGLE_QUOTED_STR, ALLOW_UNQUOTED_KEY, INSITU (modify input buffer; pad with YYJSON_PADDING_SIZE zeros), STOP_WHEN_DONE (NDJSON), JSON5.
Error: yyjson_read_err err; → err.code, err.msg, err.pos. yyjson_locate_pos(dat, len, err.pos, &line, &col, &chr) for line/col.
Access Values
yyjson_val *root = yyjson_doc_get_root(doc);
// Type checks
yyjson_is_null(v) yyjson_is_bool(v) yyjson_is_uint(v) yyjson_is_sint(v)
yyjson_is_int(v) yyjson_is_real(v) yyjson_is_num(v) yyjson_is_str(v)
yyjson_is_arr(v) yyjson_is_obj(v) yyjson_is_raw(v)
// Getters
bool b = yyjson_get_bool(v); uint64_t u = yyjson_get_uint(v);
int64_t s = yyjson_get_sint(v); int i = yyjson_get_int(v);
double d = yyjson_get_real(v); const char *str = yyjson_get_str(v);
size_t len = yyjson_get_len(v); const char *raw = yyjson_get_raw(v);
// Array (linear by index)
size_t sz = yyjson_arr_size(arr);
yyjson_val *v = yyjson_arr_get(arr, idx);
yyjson_val *v = yyjson_arr_get_first(arr) / yyjson_arr_get_last(arr);
// Object (linear by key)
size_t sz = yyjson_obj_size(obj);
yyjson_val *v = yyjson_obj_get(obj, "key");
yyjson_val *v = yyjson_obj_getn(obj, "key", key_len);
// String compare
yyjson_equals_str(v, "abc"); yyjson_equals_strn(v, "abc", 3);
Iterate
// Array
yyjson_val *v;
yyjson_arr_iter iter = yyjson_arr_iter_with(arr);
while ((v = yyjson_arr_iter_next(&iter))) { }
// Macro:
yyjson_arr_foreach(arr, idx, max, v) { }
// Object
yyjson_val *k, *v;
yyjson_obj_iter iter = yyjson_obj_iter_with(obj);
while ((k = yyjson_obj_iter_next(&iter))) { v = yyjson_obj_iter_get_val(k); }
// Macro:
yyjson_obj_foreach(obj, idx, max, k, v) { }
Mutable: use yyjson_mut_ prefix. Inside mutable iter: yyjson_mut_arr_iter_remove(&iter) / yyjson_mut_obj_iter_remove(&iter).
Create / Modify JSON
yyjson_mut_doc *doc = yyjson_mut_doc_new(alc);
yyjson_mut_val *root = yyjson_mut_obj(doc); // or yyjson_mut_arr(doc)
yyjson_mut_doc_set_root(doc, root);
// Scalars
yyjson_mut_null(doc) yyjson_mut_bool(doc, true)
yyjson_mut_uint(doc, 123) yyjson_mut_sint(doc, -123) yyjson_mut_int(doc, 123)
yyjson_mut_real(doc, 1.5) yyjson_mut_str(doc, "hello") // refs caller's string
yyjson_mut_strcpy(doc, "hello") // copies into doc
yyjson_mut_strn(doc, "hello", 5) yyjson_mut_strncpy(doc, "hello", 5) // n-variants
// Array
yyjson_mut_arr_append(arr, val) yyjson_mut_arr_prepend(arr, val)
yyjson_mut_arr_insert(arr, val, idx) yyjson_mut_arr_replace(arr, idx, val)
yyjson_mut_arr_remove(arr, idx) yyjson_mut_arr_remove_first/last(arr) yyjson_mut_arr_clear(arr)
// Convenience: yyjson_mut_arr_add_int(doc, arr, 42) / _add_str / _add_arr / _add_obj
// From C array: yyjson_mut_arr_with_sint32(doc, nums, 3)
// Object
yyjson_mut_obj_add(obj, key, val) // allows duplicates
yyjson_mut_obj_put(obj, key, val) // removes existing first (O(n))
yyjson_mut_obj_remove(obj, key) yyjson_mut_obj_clear(obj)
// Convenience: yyjson_mut_obj_add_str/int/arr/obj(doc, obj, "key", ...)
yyjson_mut_obj_remove_str(obj, "key") yyjson_mut_obj_rename_key(doc, obj, "old", "new")
Important: A yyjson_mut_val can only be added to one container.
Immutable ↔ Mutable
yyjson_mut_doc *mdoc = yyjson_doc_mut_copy(idoc, alc);
yyjson_mut_val *mval = yyjson_val_mut_copy(mdoc, ival);
yyjson_doc *idoc = yyjson_mut_doc_imut_copy(mdoc, alc);
Write JSON
char *json = yyjson_write(doc, flg, &len); free(json);
char *json = yyjson_mut_write(mdoc, flg, &len); free(json);
char *json = yyjson_val_write(val, flg, &len); free(json); // per-value
yyjson_write_file("out.json", doc, flg, alc, &err);
yyjson_mut_write_file("out.json", mdoc, flg, alc, &err);
yyjson_write_fp(fp, doc, flg, alc, &err);
size_t n = yyjson_write_buf(buf, buf_len, doc, flg, &err);
Write flags: YYJSON_WRITE_NOFLAG (minified), PRETTY (4-space), PRETTY_TWO_SPACES, ESCAPE_UNICODE, ESCAPE_SLASHES, ALLOW_INF_AND_NAN, INF_AND_NAN_AS_NULL, ALLOW_INVALID_UNICODE, LOWERCASE_HEX, NEWLINE_AT_END, FP_TO_FLOAT, FP_TO_FIXED(prec) (1..15).
JSON Pointer / Patch (RFC 6901/6902/7386)
// Query
yyjson_val *v = yyjson_doc_ptr_get(doc, "/users/0/name");
// Modify (mutable)
yyjson_mut_doc_ptr_set(doc, "/a", yyjson_mut_int(doc, 9));
yyjson_mut_doc_ptr_add(doc, "/b/-", val); // "-" appends to array
yyjson_mut_doc_ptr_remove(doc, "/b");
// Error variants: _getx takes yyjson_ptr_err; _setx/_addx/_removex take yyjson_ptr_ctx + yyjson_ptr_err
// Patch
yyjson_mut_val *out = yyjson_patch(doc, orig, patch, &err); // RFC 6902
yyjson_mut_val *out = yyjson_merge_patch(doc, orig, patch); // RFC 7386
Memory Allocator
// Stack allocator
char buf[128*1024];
yyjson_alc alc; yyjson_alc_pool_init(&alc, buf, sizeof(buf));
yyjson_doc *doc = yyjson_read_opts(dat, len, 0, &alc, NULL);
// Dynamic
yyjson_alc *alc = yyjson_alc_dyn_new();
// ...
yyjson_alc_dyn_free(alc);
// Custom (malloc/realloc/free signatures match yyjson_alc)
yyjson_alc MY_ALC = { my_malloc, my_realloc, my_free, NULL };
A custom allocator applies to the document and its values. The output string from yyjson_write() / yyjson_mut_write() / yyjson_val_write() uses the default allocator; use the _opts variants to route it through the same allocator.
Number & Compile-time
// Per-value output format (mutable)
yyjson_mut_set_fp_to_float(val, true);
yyjson_mut_set_fp_to_fixed(val, 6);
Compile-time defines: YYJSON_DISABLE_READER, YYJSON_DISABLE_WRITER, YYJSON_DISABLE_INCR_READER, YYJSON_DISABLE_UTILS (Pointer/Patch), YYJSON_DISABLE_FAST_FP_CONV, YYJSON_DISABLE_NON_STANDARD, YYJSON_DISABLE_UTF8_VALIDATION, YYJSON_DISABLE_UNALIGNED_MEMORY_ACCESS. YYJSON_READER_DEPTH_LIMIT.
Null Safety
All APIs null-check inputs — safe to chain: yyjson_get_str(yyjson_obj_get(root, "key")) returns NULL if missing. For hot loops, unsafe_ prefix skips checks: unsafe_yyjson_is_str(k), unsafe_yyjson_get_uint(v).
Common Pattern: Read → Modify → Write
yyjson_doc *idoc = yyjson_read_file("in.json", 0, NULL, NULL);
yyjson_mut_doc *doc = yyjson_doc_mut_copy(idoc, NULL);
yyjson_mut_val *root = yyjson_mut_doc_get_root(doc);
yyjson_mut_val *k, *v;
yyjson_mut_obj_iter iter = yyjson_mut_obj_iter_with(root);
while ((k = yyjson_mut_obj_iter_next(&iter))) {
v = yyjson_mut_obj_iter_get_val(k);
if (yyjson_mut_is_null(v)) yyjson_mut_obj_iter_remove(&iter);
}
yyjson_mut_write_file("out.json", doc, YYJSON_WRITE_PRETTY, NULL, NULL);
yyjson_doc_free(idoc);
yyjson_mut_doc_free(doc);
Signals
- GitHub stars
- 1k
- Forks
- 108
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
yyjson- Source
- github.com/luisagroup/luisacompute