Skip to content

jt.dump and jt.dumpJson

dump and dumpJson are a symmetric pair with instantiate: instantiate ingests and decodes wire data; dump / dumpJson encodes domain data back to wire form.


jt.dump

Declaration. Walks the canonical schema graph for the given schemaId, applies any registered Transform encoder at each node, filters the result according to options, and returns the brand-free wire InputType (LooseInputType<…>) — the wire-form JS value, never unknown. The input value is not mutated.

Options

OptionTypeDefaultDescription
mode'wire' | 'json''wire''json' converts Date values to ISO strings for JSON.stringify safety
excludereadonly string[]-Property names to drop (ignored when include is set)
includereadonly string[]-Property names to keep (takes precedence over exclude)
excludeUnsetbooleanfalseDrop properties whose runtime value is undefined
excludeDefaultsbooleanfalseDrop properties whose value strictly equals the schema default

Use this when you need to serialize a domain object back to wire form - before storing in a database, before sending over HTTP, before publishing to a queue. Use the filtering options to produce compact payloads or specific projections. Use dumpJson when you need a JSON string directly.

Don't use this when you want a complete validated object (use instantiate instead - it goes the other direction). Don't call it on raw unvalidated input - dump expects a value that has already been through instantiate or materialize.

Examples

Example 1: Basic serialization of a coerced book

/**
 * bookstoreEntities.dump — Example 1: Wire-form serialization with options
 * Demonstrates: excludeDefaults, include, basic dump
 *
 * The book is Cornelia Funke's Tintenherz (Cecilie Dressler Verlag, 2003) —
 * a contemporary German children's classic shelved alongside the
 * Neverending Story rare-book fixture in Coreander's bookshop.
 */

import {
  BookSchema, bookstoreEntities
} from '../bookstore/index.js';

const book = bookstoreEntities.instantiate(BookSchema.$id, {
  'authors': ['Cornelia Funke'],
  'isbn': '9783791504650',
  'price': {
    'amount': 19.95,
    'currency': 'EUR'
  },
  'printStatus': 'inPrint',
  'title': 'Tintenherz'
  // inStock defaults to true
});

// Basic dump — all fields including defaults.
const wire = bookstoreEntities.dump(BookSchema.$id, book);

console.assert('inStock' in wire);
console.assert((wire as { 'inStock': boolean }).inStock);

// excludeDefaults — drops inStock:true.
const compact = bookstoreEntities.dump(BookSchema.$id, book, { 'excludeDefaults': true });

console.assert(!('inStock' in (compact as object)));

// include — projection to specific fields.
const projected = bookstoreEntities.dump(BookSchema.$id, book, {
  'include': [
    'isbn',
    'title',
    'price'
  ]
});

console.assert('isbn' in (projected as object));
console.assert(!('authors' in (projected as object)));

// Show what each dump variant produces
console.log('wire (all fields):', JSON.stringify(wire, null, 2));
console.log('compact (excludeDefaults):', JSON.stringify(compact, null, 2));
console.log('projected (isbn, title, price only):', JSON.stringify(projected, null, 2));
Output
Press Execute to run this example against the real library.

Example 2: Compact payload - exclude default-valued fields

/**
 * dump — Example 2: Compact payload — exclude default-valued fields
 * Demonstrates: excludeDefaults option drops fields that equal the schema default
 *
 * Cornelia Funke's Tintenherz has `inStock: true` (schema default: true).
 * With `excludeDefaults: true`, `inStock` is omitted from the wire payload
 * because its value equals the declared default.
 */

import {
  BookSchema, bookstoreEntities
} from '../bookstore/index.js';

const book = bookstoreEntities.instantiate(BookSchema.$id, {
  'authors': ['Cornelia Funke'],
  'isbn': '9783791504650',
  'price': {
    'amount': 19.95,
    'currency': 'EUR'
  },
  'printStatus': 'inPrint',
  'title': 'Tintenherz'
  // inStock omitted — schema default true will be filled
});

// Full dump includes inStock: true (the default was applied by instantiate)
const full = bookstoreEntities.dump(BookSchema.$id, book);

console.assert('isbn' in full);

// excludeDefaults drops inStock: true because it equals the schema default
const compact = bookstoreEntities.dump(BookSchema.$id, book, { 'excludeDefaults': true });

// isbn, title, authors are required fields — always present
console.assert('isbn' in compact);
console.assert('title' in (compact as object));

// inStock: true equals the schema default, so it should be absent
console.assert(!('inStock' in (compact as object)), 'inStock should be omitted (equals default)');

// Show the two wire forms side by side
console.log('full dump (inStock included):', JSON.stringify(full, null, 2));
console.log('compact dump (inStock omitted):', JSON.stringify(compact, null, 2));
Output
Press Execute to run this example against the real library.

Example 3: Project to specific fields

/**
 * dump — Example 3: Project to specific fields using include
 * Demonstrates: include option keeps only the named properties in wire output
 *
 * Michael Ende's "Die unendliche Geschichte" — only isbn, title, and price
 * are included in the projected payload; authors is omitted.
 */

import {
  aboxFixtures, BookSchema, bookstoreEntities
} from '../bookstore/index.js';

const book = bookstoreEntities.instantiate(BookSchema.$id, {
  'authors': ['Michael Ende'],
  'isbn': aboxFixtures.rareBook.isbn,
  'price': aboxFixtures.rareBook.price,
  'printStatus': 'outOfPrint',
  'title': aboxFixtures.rareBook.title
});

const listing = bookstoreEntities.dump(BookSchema.$id, book, {
  'include': [
    'isbn',
    'title',
    'price'
  ]
});

console.assert('isbn' in listing);
console.assert('title' in (listing as object));
console.assert('price' in (listing as object));
console.assert(!('authors' in (listing as object)));
console.assert(!('inStock' in (listing as object)));

// Show the projected listing payload — isbn, title, price only
console.log('projected listing payload:', JSON.stringify(listing, null, 2));
Output
Press Execute to run this example against the real library.

Example 4: Transform integration - encode applied automatically

If the schema has a Transform encoder registered (see Transforms), dump applies the encode function at each transformed node. A instantiatedump round-trip recovers the original wire value.

/**
 * dump — Example 4: Transform integration — encode applied automatically
 * Demonstrates: instantiate → dump round-trip applies the encode function
 *
 * A PlacedAt schema wraps a date-time string with a normalize transform.
 * `instantiate` decodes the ISO string (normalizing fractional milliseconds);
 * `dump` applies encode to re-serialize. The round-trip recovers the wire value exactly.
 *
 * The timestamp is the moment Bastian Balthazar Bux placed the order for
 * Michael Ende's 1979 Thienemann first edition from Coreander's antiquariat.
 */

import { Transform } from '../../../src/index.js';
import {
  createBookstoreDocRegistry
} from '../bookstore/index.js';

// createBookstoreDocRegistry seeds a permissive copy of the bookstore — docs examples extend
// it with ad-hoc demo schemas; strict-graph checking is intentionally off here.
const jt = createBookstoreDocRegistry();

const PlacedAtDumpSchema = Transform.create(
  {
    '$id': 'https://bookstore.example/PlacedAtDump',
    'format': 'date-time',
    'type': 'string'
  } as const,
  {
    'decode': (isoString: string) => {
      // Normalize: parse and re-emit as canonical ISO string.
      // This ensures the wire value is normalized to a consistent format.
      return new Date(isoString).toISOString();
    },
    'encode': (isoString: string) => {
      // Encode reversal: return the canonical ISO string to wire.
      return isoString;
    }
  }
);

jt.set(PlacedAtDumpSchema);

const raw = '2026-01-15T10:30:00.000Z';
const canonical = jt.instantiate(PlacedAtDumpSchema, raw);

// instantiate applies the decode function — result is a canonical ISO string
console.assert(typeof canonical === 'string', 'instantiate should decode to ISO string');
console.assert(canonical === raw, 'canonical form matches raw input');

// encode applies the encode function — result is the original ISO string
const wire = jt.encode(PlacedAtDumpSchema, canonical);

console.assert(wire === raw, 'encode should re-encode canonical → original ISO string');
console.assert(typeof wire === 'string');

// Show the round-trip: ISO string → canonical ISO string → wire ISO string
console.log('raw ISO string:', raw);
console.log('canonical ISO string:', canonical);
console.log('re-encoded (wire):', wire);
Output
Press Execute to run this example against the real library.

Bad examples - what NOT to do

Anti-pattern 1: Calling dump on raw (uninstantiated) input

/**
 * dump — Anti-pattern 1: Calling dump on raw (uninstantiated) input
 * Demonstrates: dump expects an instantiated value; raw input bypasses coercion
 *
 * Michael Ende's "Die unendliche Geschichte" — the anti-pattern passes a raw
 * object directly to dump; the correct pattern instantiates first, then dumps.
 */

import {
  aboxFixtures, type Book, BookSchema, bookstoreEntities
} from '../bookstore/index.js';

// Anti-pattern: dump on raw uncoerced input — encode runs but coercion did not.
// Raw input is untrusted (`unknown`); the anti-pattern forces it past dump's
// branded value parameter, the very narrowing the correct path earns via
// instantiate. Don't do this.
const rawInput: unknown = {
  'authors': ['Michael Ende'],
  'isbn': aboxFixtures.rareBook.isbn,
  'price': aboxFixtures.rareBook.price,
  'printStatus': 'outOfPrint',
  'title': aboxFixtures.rareBook.title
};

const antipatternWire = bookstoreEntities.dump(BookSchema.$id, rawInput as Book);

void antipatternWire;

// Correct approach: instantiate first so coercion and defaults are applied,
// then dump to produce the wire form
const book = bookstoreEntities.instantiate(BookSchema.$id, rawInput);
const wireBook = bookstoreEntities.dump(BookSchema.$id, book);

console.assert('isbn' in wireBook);
console.assert('title' in (wireBook as object));

// Show the correctly-instantiated wire form (anti-pattern omitted from output)
console.log('correct wire (instantiate then dump):', JSON.stringify(wireBook, null, 2));
Output
Press Execute to run this example against the real library.

Comparison

ts
const wire = jt.dump(BookSchema.$id, book);
const wire2 = jt.dump(BookSchema.$id, book, { excludeDefaults: true });
const json = jt.dumpJson(BookSchema.$id, book); // JSON string
ts
// Zod doesn't have a separate dump/serialize step.
// The parsed value is already in the desired shape.
const json = JSON.stringify(book);
// No exclude/include filtering without manual code.
ts
// Limitation: Valibot has no dump/serialize step and no encode direction.
// JSON.stringify the value directly; encoding of branded or transformed
// fields (e.g. Date) must be applied manually before stringify.
const json = JSON.stringify(book);
ts
// Limitation: io-ts has no dump step that walks a graph and applies encoders.
// Each codec exposes .encode for itself; for a composite, call .encode at
// the top level then JSON.stringify. No filtering options.
const wire = BookCodec.encode(book);
const json = JSON.stringify(wire);
ts
// TypeBox does not have a built-in dump/serialize utility.
const json = JSON.stringify(book);
ts
// AJV validates  - no serialize step.
const json = JSON.stringify(book);
py
wire = book.model_dump()
json_str = book.model_dump_json()
# Filtering options:
book.model_dump(exclude={'currency', 'in_stock'})
book.model_dump(include={'isbn', 'title', 'price'})
book.model_dump(exclude_defaults=True)
book.model_dump(exclude_none=True)
ts
// Limitation: feature not directly supported in Yup. See /comparisons for the matrix.
ts
// Limitation: feature not directly supported in Joi. See /comparisons for the matrix.
ts
// Limitation: feature not directly supported in Effect Schema. See /comparisons for the matrix.
ts
// Limitation: feature not directly supported in ArkType. See /comparisons for the matrix.
ts
// Limitation: feature not directly supported in Runtypes. See /comparisons for the matrix.

jt.dumpJson

Declaration. Convenience wrapper around dump() with mode: 'json' forced. Equivalent to JSON.stringify(jt.dump(schemaId, value, { mode: 'json', ...options })). Returns a JSON string. The mode option is not available on dumpJson - it is always 'json'.

Use this when you need a JSON string directly - HTTP response bodies, log records, message queue payloads.

Examples

Example 1: Serialize a customer for an HTTP response

/**
 * dumpJson — Example 1: Serialize a customer for an HTTP response
 * Demonstrates: dumpJson returns a JSON string; all fields included
 *
 * Bastian Balthazar Bux — the canonical customer fixture instantiated
 * and serialized to a JSON string suitable for an HTTP response body.
 */

import {
  aboxFixtures, bookstoreEntities, CustomerSchema
} from '../bookstore/index.js';

const customer = bookstoreEntities.instantiate(CustomerSchema.$id, {
  'addresses': [aboxFixtures.order.shippingAddress],
  'customerId': 'c1a2b3d4-e5f6-7890-abcd-ef1234567890',
  'email': 'bastian.bux@bookstore.example',
  'name': 'Bastian Balthazar Bux'
});

const json = bookstoreEntities.dumpJson(CustomerSchema.$id, customer);

// dumpJson always returns a string
console.assert(typeof json === 'string');

const parsed = JSON.parse(json) as Record<string, unknown>;

console.assert(parsed.customerId === 'c1a2b3d4-e5f6-7890-abcd-ef1234567890');
console.assert(parsed.email === 'bastian.bux@bookstore.example');
console.assert(parsed.name === 'Bastian Balthazar Bux');
console.assert(Array.isArray(parsed.addresses));

// Show the JSON string as it would appear in an HTTP response body
console.log('HTTP response body:', json);
Output
Press Execute to run this example against the real library.

Example 2: Compact order payload

/**
 * dumpJson — Example 2: Compact order payload
 * Demonstrates: dumpJson with excludeDefaults produces a shorter JSON string
 *
 * Bastian Balthazar Bux orders the 1979 Thienemann first edition. With
 * `excludeDefaults: true`, any fields equal to their schema defaults are
 * omitted from the JSON string.
 */

import {
  aboxFixtures, bookstoreEntities, OrderSchema
} from '../bookstore/index.js';

const order = bookstoreEntities.instantiate(OrderSchema.$id, aboxFixtures.order);

// Full JSON — all fields including any schema defaults
const fullJson = bookstoreEntities.dumpJson(OrderSchema.$id, order);

// Compact JSON — defaults omitted
const compactJson = bookstoreEntities.dumpJson(OrderSchema.$id, order, { 'excludeDefaults': true });

console.assert(typeof fullJson === 'string');
console.assert(typeof compactJson === 'string');

// Compact should be shorter or equal in length (no defaults, no extra fields)
console.assert(compactJson.length <= fullJson.length);

const compact = JSON.parse(compactJson) as Record<string, unknown>;

// Required fields are always present
console.assert(typeof compact.orderId === 'string');
console.assert(typeof compact.customerId === 'string');
console.assert(Array.isArray(compact.orderLines));

// Show both JSON strings
console.log('full JSON:', fullJson);
console.log('compact JSON (excludeDefaults):', compactJson);
Output
Press Execute to run this example against the real library.

Comparison

ts
const json = jt.dumpJson(CustomerSchema.$id, customer);
// JSON string; Date fields encoded to ISO via Transform encoders
ts
const json = JSON.stringify(customer);
// Date objects must be converted manually before stringify.
ts
// Limitation: no dumpJson; JSON.stringify works only for plain values.
const json = JSON.stringify(customer);
ts
// Limitation: no dumpJson convenience; combine .encode and JSON.stringify.
const json = JSON.stringify(CustomerCodec.encode(customer));
ts
const json = JSON.stringify(customer);
ts
const json = JSON.stringify(customer);
py
json_str = customer.model_dump_json()
# Equivalent; datetime fields serialized to ISO automatically.
ts
// Limitation: feature not directly supported in Yup. See /comparisons for the matrix.
ts
// Limitation: feature not directly supported in Joi. See /comparisons for the matrix.
ts
// Limitation: feature not directly supported in Effect Schema. See /comparisons for the matrix.
ts
// Limitation: feature not directly supported in ArkType. See /comparisons for the matrix.
ts
// Limitation: feature not directly supported in Runtypes. See /comparisons for the matrix.

See also

Released under the MIT License.