JSON
Typed and dynamic JSON. JSON.stringify covers numbers, strings, booleans, arrays (mixed ones included), objects, pretty-printing, a class toJSON() override, and whole dynamic trees; JSON.parse projects the parse tree onto a declared target type when one is annotated, and otherwise keeps the tree fully dynamic — objects as runtime property bags, arrays as dynamic arrays — so untyped `const data = JSON.parse(s)` works like JS. A few literal-only argument restrictions remain on the pretty-printer.
JSON.stringify(number)
ExactSerializes a number to its JSON text. Integers and floats both round-trip through the type-directed path.
Returnsstring — The JSON representation.
const n: number = 42
console.log(JSON.stringify(n)) // 42JSON.stringify(string)
ExactSerializes a string with the JSON escaping rules (double-quoted, embedded quotes escaped).
Returnsstring — The quoted, escaped JSON string.
const esc: string = "say 'hi'"
console.log(JSON.stringify(esc)) // 'say \"hi\"'JSON.stringify(number[])
ExactSerializes a numeric array to a JSON array. An empty array renders as [].
Returnsstring — A JSON array.
const nums: number[] = [1, 2, 3]
console.log(JSON.stringify(nums)) // [1,2,3]JSON.stringify(string[])
ExactSerializes a string array, each element quoted and escaped.
Returnsstring — A JSON array of strings.
const words: string[] = ['foo', 'bar', 'baz']
console.log(JSON.stringify(words)) // ['foo','bar','baz']JSON.stringify(object)
ExactSerializes an object's fields, including nested object literals. Date fields serialize as an ISO string via their own toISOString path.
Returnsstring — A JSON object.
const person = { name: 'Alexandros', address: { city: 'Thessaloniki', zip: 10001 } }
console.log(JSON.stringify(person))
// {"name":"Alexandros","address":{"city":"Thessaloniki","zip":10001}}JSON.stringify(boolean[])
ExactSerializes a boolean array to true/false JSON literals.
Returnsstring — A JSON array of booleans.
const flags: boolean[] = [true, false, true]
console.log(JSON.stringify(flags)) // [true,false,true]JSON.stringify(object[])
ExactSerializes an array of objects, each object rendered by its field set.
Returnsstring — A JSON array of objects.
const points: Point[] = [{ x: 1, y: 2 }, { x: 3, y: 4 }]
console.log(JSON.stringify(points)) // [{"x":1,"y":2},{"x":3,"y":4}]JSON.stringify(value, null, space) — pretty-printing
ExactPretty-prints with an indent unit and a space after each colon. A numeric space indents with N spaces (capped at 10); a string space is used literally as the indent unit (its first 10 characters). The space and a replacer — a function called with each key and value, or a property list — may be values known only at run time. Empty containers stay inline even when pretty-printing.
Returnsstring — Indented JSON text.
console.log(JSON.stringify(user, null, 2))
// {
// "name": "bob",
// "active": true,
// ...
// }JSON.stringify honors a class toJSON()
ExactA class with a toJSON() method serializes its result instead of its own fields, matching JS — same override dispatch as toString(). A toJSON() returning its own type is bounded against compile-time infinite recursion. Date keeps its own toISOString-based path rather than being unified.
Returnsstring — The JSON of the toJSON() result.
class Money {
amount: number = 42
currency: string = 'EUR'
toJSON(): string { return this.amount + this.currency }
}
console.log(JSON.stringify(new Money())) // "42EUR"JSON.stringify(mixedTypeArray)
Works, with caveatsA mixed literal is an array of the union of its element types, as TypeScript infers it; each element serializes by its run-time kind, class instances and plain objects included.
class P { x = 1 }
console.log(JSON.stringify([new P(), 2, null])) // [{"x":1},2,null]- Strict lane: a literal mixing two object types, or an untyped [] grown with values of different types, is rejected
JSON.parse(s) → number
ExactParses a numeric JSON string. Integers go through atoll, floats (including a float64/float32-typed variable) through strtod on the node's raw lexeme, via the type-directed projection.
Returnsnumber — The parsed number.
const parsed: number = JSON.parse('123')
console.log(parsed) // 123JSON.parse(s) → object
ExactType-directed projection off the parse tree: nested objects, array-typed fields, and object-array fields (Item[]) all project through one path. A nullable-scalar field keeps its null-vs-value boxing; a missing field falls back to its type's default.
ReturnsT — An instance of the annotated target type.
interface Member { name: string; addr: Addr; tags: string[] }
const m: Member = JSON.parse('{"name":"Nikos","addr":{"city":"Thessaloniki","zip":54600},"tags":["admin","dev"]}')
console.log(m.addr.city) // ThessalonikiJSON.parse(s) → top-level T[]
Works, with caveatsProjects the tree's array node into the standard {ptr,i64} aggregate, reusing the array-literal build path, including object and nested arrays.
ReturnsT[] — The parsed array in an annotated position.
const members: Member[] = JSON.parse('[{"name":"A","addr":{"city":"X","zip":1},"tags":[]},{"name":"B","addr":{"city":"Y","zip":2},"tags":["x"]}]')
console.log(members.length) // 2- A typed var-decl, an object field, and a declared-variable reassignment (
let xs: T[] = …; xs = JSON.parse(...)) all project; a member or element target (obj.items = JSON.parse(...),grid[i] = …) does not — assign into a variable first.
JSON.parse(s) validates input
Works, with caveatsA real recursive-descent parser builds and validates a tagged value tree. Strict JSON only (double quotes, no trailing commas/leading zeros/trailing junk), with \uXXXX + surrogate decoding and a 512-deep runtime depth guard on untrusted input. A malformed input throws a catchable SyntaxError; Response.json() inherits the same parser.
ReturnsT — The parsed value, or throws SyntaxError.
try {
const bad: number = JSON.parse("{oops}")
} catch (e) {
console.log(e.name) // SyntaxError
}- The
SyntaxErrormessage is position-based (Unexpected token in JSON at position N), not Node/V8's exact per-token wording
JSON.parse(s) → any/unknown (dynamic shape)
implementedUntyped (or any-annotated) JSON.parse keeps the whole tree as dynamic values: objects become runtime property bags, arrays real dynamic arrays with .length, index reads/writes, and for...in — so member chains like data.server.ports[0] work without a declared shape. JSON.stringify serializes the dynamic tree back (round-trip clean): undefined values are skipped in objects and become null in arrays, and a circular structure throws the Node-matching TypeError. The space argument pretty-prints a dynamic value byte-identically to the typed path. Operations beyond property access on the dynamic values follow the normal any limits until narrowed.