Recursive AI

Read YAML without a schema

All oneyaml Rust recipes

When you don’t have a struct for the data, read it into oneyaml::Value and index it like serde_json::Value.

RUST
use oneyaml::Value;
 
fn main() -> Result<(), oneyaml::Error> {
    let src = "\
server:
  host: 0.0.0.0
  port: 8080
features: [auth, metrics]
limits:
  cpu: 0.5
  memory: 512Mi
";
    let v: Value = oneyaml::from_str(src)?;
 
    // Index by key or position; a missing key gives Value::Null, not a panic.
    println!("host     = {:?}", v["server"]["host"].as_str());
    println!("port     = {:?}", v["server"]["port"].as_u64());
    println!("feature0 = {:?}", v["features"][0].as_str());
    println!("missing  = {:?}", v["server"]["tls"].as_str());
 
    // Walk a mapping in file order.
    if let Some(limits) = v["limits"].as_mapping() {
        for (k, val) in limits {
            println!("limit {} = {:?}", k.as_str().unwrap_or("?"), val);
        }
    }
    Ok(())
}
Text
host     = Some("0.0.0.0")
port     = Some(8080)
feature0 = Some("auth")
missing  = None
limit cpu = Number(0.5)
limit memory = String("512Mi")

Good to know

  • Indexing with v["key"] or v[0] never panics: a missing key or index gives Value::Null, so as_str() and friends return None.
  • A mapping keeps the order of the file.
  • 0.5 is a number and 512Mi a string: the Core schema decides, the same way for Value as for a struct.
  • To read values and also edit the file, use a Document instead: doc.get_path("server.port") reads a node with its span, comments and style (edit YAML and keep its comments).
  • oneyaml::from_value turns a Value into a typed struct later, once you know which one it is.