Your first mapping
In this tutorial you’ll turn a legacy book record into a clean catalog entry without writing transformation code. You’ll describe the result you want in a mapping document, apply it, and let the mapping validate its own output.
You’ll need Deno 2 installed. Everything else arrives in step 1.
1. Create a project
Section titled “1. Create a project”mkdir first-mapping && cd first-mappingdeno add jsr:@christiansmith/mapper-js jsr:@std/yaml2. Describe the shape you want
Section titled “2. Describe the shape you want”A mapping is a document. Each line pairs a target location, where to
write in the output, with a descriptor of what to read. Save this as
mapping.yaml:
/book/title: /name/book/year: { source: /published, as: number }/book/language: { source: /lang, default: en }Read the first line as: the output’s /book/title comes from the input’s
/name. Locations on both sides are JSON
Pointers. The second pairing coerces
the value to a number with as. The third falls back to en with default
when the input has no /lang.
3. Provide an input
Section titled “3. Provide an input”Save this as input.json:
{ "name": "The Compleat Mapper", "published": "1998", "shelf": "B4" }4. Apply the mapping
Section titled “4. Apply the mapping”Save this as main.js:
import Mapper from '@christiansmith/mapper-js'import { parse } from '@std/yaml'
const mapping = parse(await Deno.readTextFile('mapping.yaml'))const input = JSON.parse(await Deno.readTextFile('input.json'))
const mapper = new Mapper({}, { initializers: {}, transformers: {}, plugins: {} })const { valid, errors, ...result } = await mapper.map(mapping, input)
console.log(JSON.stringify(result, null, 2))Run it:
deno run --allow-read main.jsYou should see:
{ "book": { "title": "The Compleat Mapper", "year": 1998, "language": "en" }}Three things happened. as turned "1998" into the number 1998. default
filled in language. And shelf didn’t come along. A mapping only reads
what it addresses. Unmapped input stays out of the output.
5. Let the mapping validate its output
Section titled “5. Let the mapping validate its output”Suppose a catalog entry is unusable without an ISBN. Add one more pairing to
mapping.yaml:
/book/isbn: { source: /isbn, required: true }Run main.js again, printing the whole envelope this time
(console.log(valid, errors)). The input has no /isbn, so instead of a
partial result you get:
valid: falseerrors: - { source: /isbn, required: true, message: required value }Any error empties the result. The mapper never returns a half-valid document.
Add an "isbn" to the input and the mapping goes green again.
Where you are
Section titled “Where you are”You’ve written a mapping document, applied it, and made it guard its own output. That’s the whole engine loop. Next: Mapping collections, where one mapping fans out over an array of records.