Packages

yaml

Read and write YAML, the format most config files are written in.

import "std:yaml"

yaml reads and writes YAML. Use it for configuration that people edit by hand: it has comments, no quoting noise and readable nesting. Parsing gives you ordinary OSL values (objects, arrays, strings, numbers), the same ones json gives you, so the code that uses the data doesn't care which format it came from.

osl
import "std:yaml"

Parse a document#

yaml.parse returns a result. Mappings become objects, sequences become arrays, and scalars become strings, numbers, booleans or null.

main.osl
import "std:yaml"

string text = `
name: shop
port: 8080
debug: false
owner: ~
tags:
  - web
  - prod
db:
  host: localhost
  pool: 4
`

auto cfg = yaml.parse(text).unwrap()
log cfg.name cfg.port cfg.debug cfg.owner
log cfg.tags[2]
log cfg.db.host cfg.db.pool
Click the code to edit it

Comments start with # and are dropped. An empty document parses to null.

Try it: add a replicas: 3 line to the text and log it.

Errors#

Bad indentation, a duplicate key or an unclosed bracket is a ParseError. The message says which line.

main.osl
import "std:yaml"

string[] docs = ["a: 1\nb: [1, 2", "a: 1\na: 2", "ok: true"]
for d in docs (
  switch yaml.parse(d) (
    case ok(v)
      log "ok"
    case err(e)
      log e.kind
  )
)
log yaml.isValid("x: 1") yaml.isValid("x: [")
Click the code to edit it

Try it: fix the first document's missing bracket and watch ParseError disappear.

Some YAML surprises#

YAML guesses types from how a value looks. yes is not special here, but true, null, numbers and ~ are. Quote anything that must stay text. Timestamps are left as the strings you wrote.

main.osl
import "std:yaml"

auto v = yaml.parse(`
version: 1.10
code: "007"
when: 2026-11-15
empty:
`).unwrap()
log v.version v.code v.when v.empty
Click the code to edit it

Note version: 1.10 became the number 1.1. If a value is a version or an identifier, quote it in the file.

Anchors and multi-line text#

Anchors (&name) and aliases (*name) let you reuse a block. Block scalars (| keeps newlines, > folds them) hold long text.

main.osl
import "std:yaml"

auto cfg = yaml.parse(`
defaults: &defaults
  retries: 3
  timeout: 30
prod:
  <<: *defaults
  timeout: 60
banner: |
  Hello
  world
`).unwrap()
log cfg.prod.retries cfg.prod.timeout
log cfg.banner.len
Click the code to edit it

Write YAML#

yaml.stringify turns a value into YAML, with keys in sorted order and a trailing newline. The indent option sets the spaces per level (2 to 16, default 4).

main.osl
import "std:yaml"

auto data = {name: "shop", ports: [80, 443], db: {host: "localhost", pool: 4}}
log yaml.stringify(data, {indent: 2})
Click the code to edit it

Strings that would be read back as something else are quoted for you, so parse(stringify(x)) gives x back.

main.osl
import "std:yaml"

auto back = yaml.parse(yaml.stringify({a: "true", b: "12", c: "plain"})).unwrap()
log back.a back.b back.c
log back.a == "true"
Click the code to edit it

Try it: change indent to 4 and compare.

Files#

yaml.parseFile reads a file. A missing file is NotFoundError, a bad one is ParseError.

main.osl
import "std:yaml"
import "std:fs"

fs.writeFile("app.yaml", yaml.stringify({name: "demo", workers: 2})).unwrap()
auto app = yaml.parseFile("app.yaml").unwrap()
log app.name app.workers
log yaml.parseFile("nope.yaml").unwrapErr().kind
Click the code to edit it

Converting between formats#

Because every format gives the same values, converting is a parse and a stringify:

main.osl
import "std:yaml"
import "std:json"

auto doc = yaml.parse("a: 1\nlist:\n  - x\n  - y\n").unwrap()
log json.stringify(doc)
Click the code to edit it
Quick check

In YAML, version: 1.10 is read as...

Your turn

Add up the ports

Parse the YAML and print the name, then the sum of the ports.

main.osl
Ctrl Enter runs
Expected output
demo 523

API reference#

14 members, generated from the std:yaml source of OSL 9.3.0.

Functions

#yaml.delete(object data, any key) object

Deprecated. Deprecated: use data.delete(key) instead.

delete removes key from data in place and returns data.

#yaml.fromJSON(any jsonData) any

Deprecated. Deprecated: use json.parse(text) instead.

fromJSON decodes any JSON value (object, array or scalar); invalid JSON gives null.

#yaml.get(any data, any key) any

Deprecated. Deprecated: use data[key] instead.

get reads data[key], or null.

#yaml.has(object data, any key) boolean

Deprecated. Deprecated: use data.contains(key) instead.

has reports whether data has key.

#yaml.isValid(string text) boolean

isValid reports whether yaml.parse would accept text.

#yaml.keys(object data) array

Deprecated. Deprecated: use data.getKeys().sort() instead.

keys lists data's keys in sorted order.

#yaml.merge(object data1, object data2) object

Deprecated. Deprecated: use {...data1, ...data2} for a shallow merge, or merge nested objects with a loop, instead.

merge deep-merges data2 into a copy of data1: nested objects merge, and any other value in data2 replaces data1's.

#yaml.mergeCloned(object data1, object data2) object

Deprecated. Deprecated: use {...data1, ...data2} for a shallow merge, or merge nested objects with a loop, instead.

mergeCloned is yaml.merge under another name.

#yaml.parse(string text) result<any, error>

parse reads a YAML document from text into OSL values: mappings become objects (keys as strings), sequences arrays, and scalars strings, numbers, booleans or null; timestamps stay strings as written. An empty document is null. Fails with ParseError, naming the line, for malformed YAML, duplicate keys and recursive aliases.

#yaml.parseFile(string path) result<any, error>

parseFile reads and parses the YAML file at path like yaml.parse. Fails with NotFoundError, PermissionError or IOError when the file can't be read and ParseError when it isn't valid YAML.

#yaml.set(object data, any key, any value) object

Deprecated. Deprecated: use data[key] = value instead.

set sets data[key] = value in place and returns data.

#yaml.stringify(any value, object? options) string

stringify encodes value as YAML text, with object keys in sorted order and a trailing newline. Options: indent (spaces per nesting level, 2 to 16, default 4). Throws TypeError for values YAML can't represent, such as functions, and ValueError for a value that contains itself.

#yaml.toJSON(any yamlData) string

Deprecated. Deprecated: use json.stringify(yaml.parse(text)) instead.

toJSON converts YAML text to JSON text, or a JSON {"error": message} object when the YAML is malformed.

#yaml.values(object data) array

Deprecated. Deprecated: use data.getValues() instead.

values lists data's values.