js-yaml@4 to js-yaml@5 js-yaml v5 has a new API and a new YAML implementation. load() and dump()
stay, but exports, schemas, options and custom tags changed. Work through the
sections in order and skip the ones you don't use.
If you only load() and dump() without options, this is the whole migration:
swap the import and you're done.
// v4
const yaml = require('js-yaml')
try {
yaml.load(source)
} catch (e) {
console.error(e)
}
yaml.dump(data)
// v5
import { load, dump } from 'js-yaml'
try {
load(source)
} catch (e) {
console.error(e)
}
dump(data)
CommonJS keeps working through destructuring:
const { load, dump } = require('js-yaml')
If you want to keep the old namespace-style calls, import the ESM namespace instead:
import * as yaml from 'js-yaml'
try {
yaml.load(source)
} catch (e) {
console.error(e)
}
yaml.dump(data)
js-yaml v5 does not provide an ESM default export by design. Prefer named
exports for new code, or use the namespace import above when migrating code that
expects yaml.load() / yaml.dump().
Exports are now flat. The types namespace, the Type class and
DEFAULT_SCHEMA are gone, and internal js-yaml/lib/... imports no longer
resolve. If you used any of those, read on.
| Removed option | What to do |
|---|---|
onWarning, legacy |
nothing — errors are still thrown |
listener |
was a workaround for the missing AST; v5 exposes events and an AST to build your own pipeline |
load('') now throws: an empty stream has no document, and load has no output
value to signal its absence. Previously it cheated on types and returned
undefined; now it just throws an error.
loadAll('') is unchanged — it still returns an empty array of documents.
load() now uses the YAML 1.2 CORE_SCHEMA, as recommended by the spec author.
In practice the most common compatibility difference is the missing !!merge
(<<) feature, which is easy to add back:
import { load, CORE_SCHEMA, mergeTag } from 'js-yaml'
try {
load(source, { schema: CORE_SCHEMA.withTags(mergeTag) })
} catch (e) {
console.error(e)
}
If you need the legacy YAML 1.1 types (!!timestamp, !!binary, !!set) or
its slightly different int/float/boolean syntax, pass YAML11_SCHEMA:
import { load, YAML11_SCHEMA } from 'js-yaml'
try {
load(source, { schema: YAML11_SCHEMA })
} catch (e) {
console.error(e)
}
To register custom tags on a schema, Schema.extend() is now
Schema.withTags().
Simple keys (numbers, strings) are still stringified, but complex keys (arrays, objects) now throw instead of being silently coerced to a lossy string.
You can restore the old behavior, though it's not recommended:
import { load, CORE_SCHEMA, legacyMapTag } from 'js-yaml'
try {
load(source, { schema: CORE_SCHEMA.withTags(legacyMapTag) })
} catch (e) {
console.error(e)
}
Alternatively, get real Map instances with no key restrictions — then it's
your job to handle them:
import { load, CORE_SCHEMA, realMapTag } from 'js-yaml'
try {
load(source, { schema: CORE_SCHEMA.withTags(realMapTag) })
} catch (e) {
console.error(e)
}
The YAML 1.1 !!set tag now produces a Set instead of an object of nulls:
try {
load('!!set { one, two }', { schema: YAML11_SCHEMA })
// Set { 'one', 'two' }
} catch (e) {
console.error(e)
}
By default dump now uses YAML11_SCHEMA, slightly extended with YAML 1.2
0o... ints and exponent-only floats. This guarantees safe quoting for all YAML
versions. If you don't need deep compatibility, you can pass CORE_SCHEMA to
options.
| Removed option | What to do |
|---|---|
styles |
override the tag's represent() (see below) |
replacer |
removed — patch the data before dump() |
noCompatMode |
select the schema whose scalar rules apply |
condenseFlow |
flowSkipCommaSpace, flowSkipColonSpace, quoteFlowKeys |
quotingType |
quoteStyle: 'single' or quoteStyle: 'double' |
noArrayIndent |
seqNoIndent |
stylesPatch the tag whose output you want to change:
import { CORE_SCHEMA, dump, nullCoreTag } from 'js-yaml'
const schema = CORE_SCHEMA.withTags({ ...nullCoreTag, represent: () => '~' })
dump({ value: null }, { schema })
If you style int/float and want to keep quoting safe, patch resolve too, as the
default dump schema does:
import { YAML11_SCHEMA, dump, NOT_RESOLVED, intYaml11Tag, intCoreTag } from 'js-yaml'
const schema = YAML11_SCHEMA.withTags({
...intYaml11Tag,
represent: (value) => value >= 0 ? `0x${value.toString(16)}` : value.toString(10),
resolve: (source, isExplicit) => {
const result = intYaml11Tag.resolve(source, isExplicit)
return result === NOT_RESOLVED ? intCoreTag.resolve(source, isExplicit) : result
}
})
The Type class is gone. Tags are now built with defineScalarTag,
defineSequenceTag or defineMappingTag (pick by node kind); one tag describes
both loading and dumping, and you register it via schema.withTags(...).
The model is different, not just renamed: instead of one construct(data), the
collection tags build incrementally (create + addItem / addPair), scalars
return the value or NOT_RESOLVED, and instanceOf becomes identify.
identify is required because it explicitly controls whether the tag may be
selected when dumping. For a load-only tag, use identify: () => false.
// v4
const pointType = new yaml.Type('!point', {
kind: 'sequence',
construct: data => new Point(...data),
instanceOf: Point,
represent: point => [point.x, point.y]
})
// v5
import { defineSequenceTag } from 'js-yaml'
const pointTag = defineSequenceTag('!point', {
create: () => new Point(),
addItem: (point, value, index) => {
if (index === 0) point.x = value
if (index === 1) point.y = value
},
identify: value => value instanceof Point,
represent: point => [point.x, point.y]
})
If the result cannot be populated incrementally, collect its contents in a
temporary carrier and add finalize:
const pointTag = defineSequenceTag('!point', {
create: () => [],
addItem: (items, value) => { items.push(value) },
finalize: items => new ImmutablePoint(...items),
identify: value => value instanceof ImmutablePoint,
represent: point => [point.x, point.y]
})
An anchored tag with a temporary carrier cannot recursively alias itself,
because its result does not exist until finalize returns. Such input throws.
This only sketches the shape. See Custom tags for complete documentation.