lib:json
Stable
Structural handles for JSON documents. Two userdata types — Object and Array — plus a null sentinel distinct from Lua nil. Constructed via json.object/json.array, or received populated from vnd:serde_json.
| Property | Value |
|---|---|
| Namespace | lib |
| Source | src/lua/lib/json.rs |
| Tests | tests/lib/json.test.luau |
| Stability | Stable |
| Sharable | No — Object, Array, json.null are not Sendable |
Syntax
local json = require("lib:json")Description
Explicit access — no obj.field sugar, no arr[1] indexing. Reads via :get(...), writes via :set(...)/:push(...), presence via :has(...), length via :len(). Keeps document semantics legible under Luau strict mode.
Not Sendable. Cannot appear in shared table of thread.spawn. Serialise to string via vnd:serde_json and pass through args for cross-worker transfer.
Module functions
json.object
json.object(): ObjectReturns empty mutable Object handle.
json.array
json.array(): ArrayReturns empty mutable Array handle.
json.null
json.null: anyUnique userdata sentinel for JSON null (distinct from Lua nil = "key absent"). Comparable by ==. Same value within and across workers — serde_json.from_str("null") == json.null. Not Sendable.
Object methods
Object:get(...path) : Walks path through nested Objects/Arrays. Segments: string (key) or integer (1-based index). Returns: Lua scalar for leaves, json.null for explicit nulls, Object/Array handle for containers, nil if missing.
Object:set(key, value) : Assigns value at key. Accepts: scalars, plain tables (recursive convert), Object/Array handles, json.null.
Object:has(key) : true if key present (including when value is json.null).
Object:keys() : Array of keys. Order not guaranteed.
Object:len() : Number of entries.
Object:to_table() : Deep Lua-table copy. Mutations to returned table don't affect document.
Array methods
Array:get(...path) : Same path-walking as Object. Leading segment is 1-based integer.
Array:set(index, value) : Assigns at 1-based index.
Array:push(value) : Appends to end.
Array:len() : Number of elements.
Errors
:get(...) returns nil on missing path (no raise). Type mismatches at write time raise synchronously.
Examples
Parse, navigate, mutate
local json = require("lib:json")
local serde_json = require("vnd:serde_json")
local doc = serde_json.from_str('{"name":"Alice","age":30,"tags":["a","b"]}')
print(doc:get("name")) -- Alice
print(doc:get("tags", 2)) -- b
print(doc:has("missing")) -- false
doc:set("city", "Springfield")
doc:get("tags"):push("c")
print(serde_json.to_string(doc)) -- {"age":30,"city":"Springfield",...}Null vs absent
local json = require("lib:json")
local serde_json = require("vnd:serde_json")
local v = serde_json.from_str('{"explicit":null}')
print(v:has("explicit")) -- true
print(v:get("explicit") == json.null) -- true
print(v:has("missing")) -- false
print(v:get("missing")) -- nilNested handle observes mutation
local serde_json = require("vnd:serde_json")
local doc = serde_json.from_str('{"nested":{"x":1}}')
local nested = doc:get("nested")
doc:set("nested", { x = 99, y = 100 })
print(nested:get("x")) -- 99
print(nested:get("y")) -- 100Building from scratch
local json = require("lib:json")
local arr = json.array()
arr:push(1)
arr:push("two")
arr:push(true)
local obj = json.object()
obj:set("name", "Alice")
obj:set("scores", arr)
obj:set("missing", json.null)Acceptance
Exercised by tests/lib/json.test.luau:
- Constructors.
json.object()/json.array()→ empty,:len()== 0. - Round-trip.
serde_json.from_str('{"a":1}')→ Object,:get("a")== 1. - Variadic path walk.
'{"user":{"tags":["x","y"]}}'→:get("user","tags",2)=="y". Missing →nil. - Null vs absent.
'{"explicit":null}'→:has("explicit")true,:get("explicit") == json.null.:has("missing")false,:get("missing")nil. - Scalar JSON values.
'"hi"'→"hi".'42'→ 42.'true'→ true.'null'→json.null. - Nested handle observes mutation. Handle from
:get("nested")reflects changes afterdoc:set("nested", ...). - Array ops.
:pushincrements:len().:get(n)returns element.:set(n, y)overwrites. - Object keys.
#obj:keys() == obj:len(). to_tablesnapshot. Table mutations don't affect document.- Not Sendable. Object/Array/
json.nullinshared→ raises.
See also
vnd:serde_json— parser/serialiserstd:thread— Sendable protocolvnd:jsonschema— schema validation- The module system