A YAML 1.2 parser/formatter for R, implemented in Rust for speed and correctness. Built on the excellent saphyr crate.
Installation
You can install yaml12 from CRAN with:
install.packages("yaml12")You can install the development version of yaml12 from GitHub with:
# install.packages("pak")
pak::pak("posit-dev/r-yaml12")Quick start
library(yaml12)
yaml <- "
title: A modern YAML parser and emitter written in Rust
properties: [fast, correct, safe, simple]
sequences:
simplify: true
"
doc <- parse_yaml(yaml)
str(doc)
#> List of 3
#> $ title : chr "A modern YAML parser and emitter written in Rust"
#> $ properties: chr [1:4] "fast" "correct" "safe" "simple"
#> $ sequences :List of 1
#> ..$ simplify: logi TRUEReading and writing files
value_out <- list(alpha = 1L, nested = c(TRUE, NA))
write_yaml(value_out, "my.yaml")
value_in <- read_yaml("my.yaml")
stopifnot(identical(value_out, value_in))
# Multi-document streams
docs_out <- list(list(foo = 1L), list(bar = c(2L, NA)))
write_yaml(docs_out, "my-multi.yaml", multi = TRUE)
docs_in <- read_yaml("my-multi.yaml", multi = TRUE)
stopifnot(identical(docs_in, docs_out))Tag handlers
Handlers let you opt into custom behavior for tagged nodes while keeping the default parser strict and safe.
yaml <- "
- !upper [rust, r]
- !expr 6 * 7
"
handlers <- list(
"!expr" = function(x) eval(str2lang(x), baseenv()),
"!upper" = toupper
)
parse_yaml(yaml, handlers = handlers)
#> [[1]]
#> [1] "RUST" "R"
#>
#> [[2]]
#> [1] 42Non-string mapping keys
YAML mappings can use keys that R cannot store directly as names (for example, booleans, numbers, or tagged strings). When that happens, parse_yaml() still returns a named list but also attaches a yaml_keys attribute containing the original YAML keys:
Formatting and round-tripping
The yaml_tag and yaml_keys attributes are also hooks for customizing output: tags on values round-trip, and yaml_keys allows you to emit mappings with non-string or tagged keys that can’t be represented as an R name.
obj <- list(
seq = 1:2,
map = list(key = "value"),
tagged = structure("1 + 1", yaml_tag = "!expr"),
keys = structure(
list("a", "b", "c"),
names = c("plain", "", ""),
yaml_keys = list("plain", TRUE, structure("foo", yaml_tag = "!custom"))
)
)
yaml <- format_yaml(obj)
cat(yaml)
#> seq:
#> - 1
#> - 2
#> map:
#> key: value
#> tagged: !expr 1 + 1
#> keys:
#> plain: a
#> true: b
#> !custom foo: c
roundtripped <- parse_yaml(yaml)
identical(obj, roundtripped)
#> [1] TRUEDocumentation
- YAML quick primer: https://posit-dev.github.io/r-yaml12/articles/yaml-2-minute-intro.html.
- Tags, handlers, anchors, and advanced YAML features: https://posit-dev.github.io/r-yaml12/articles/yaml-tags-and-advanced-features.html.