Change a YAML file from Rust the way a person would: one value, one list item, one new key, and every comment, blank line and quote elsewhere stays as it was. Parse it into a Document, edit, and write it back.
use oneyaml::Document; fn main() -> Result<(), Box<dyn std::error::Error>> { let src = "\ # App settings, edited by hand and by tools. server: host: 0.0.0.0 port: 8080 # behind the load balancer # Feature flags features: - auth - legacy-export # remove after the 2.0 release - metrics "; let mut doc = Document::parse(src)?; // Change one value: its trailing comment stays. doc.set_path("server.port", 9090)?; // Remove a list item: its comment goes with it. let removed = doc.get_mut("features")?.remove_at(1)?; println!("removed {:?} with {:?}", removed.text(), removed.comments()); // Add a key with a comment of its own. let mut server = doc.get_mut("server")?; let mut timeout = server.insert("timeout", "30s")?; timeout.set_trailing(Some("per request"))?; print!("{doc}"); Ok(()) }
removed "legacy-export # remove after the 2.0 release" with ["# remove after the 2.0 release"] # App settings, edited by hand and by tools. server: host: 0.0.0.0 port: 9090 # behind the load balancer timeout: 30s # per request # Feature flags features: - auth - metrics
Good to know
- Comments stay with their entry. The
# behind the load balancercomment stays onport, and the comment of the removed item goes with it. Which entry owns a comment is decided by numbered rules;doc.explain_comment(id)says which rule applied. - A removed entry isn’t lost.
remove_atreturns aRemovedwith the entry’s text and comments, which you can put back elsewhere withinsert_removed.remove_keep_commentsremoves an entry but leaves its comments in place. - Values keep their style.
set_pathandNodeMut::setkeep the old value’s quotes, block style or tag when they still fit the new value. - Comments of your own.
set_trailingwrites the comment after a value,set_leadingthe lines above it, andDocument::set_headerthe comment at the top of the file.set_blank_lines_beforeadds spacing. - An untouched document writes back byte for byte:
Document::parse(src)?.to_string() == src.
To change many values at once from a JSON document, use a patch: merge or patch YAML.
The same edit in Go, Rust and C#: Edit YAML without losing comments.