3

I have big complex YAML file, which I successfully read into serde_yaml::Value and need to send to the user (from Axum handler) as JSON.

But somewhere deep inside that big YAML there are keys like null. And serde_json::json! panics with message "key must be a string".

I understand that this is valid case for YAML, but not valid for JSON.
But is there some workaround for that? I just need string keys like "null" in place of those nulls.

JavaScript and Go YAML parsers behaves exactly like this...

I wrote a big recursive function for that, which manually converts values, but maybe this is overkill. And also my function somehow breaks YAML merges (<<), don't know why yet.

yumaa
  • 965
  • 9
  • 18

1 Answers1

1

You can simply deserialize the yaml into a serde_json::Value instead, that way it's guaranteed to be serializable to json later:

fn main() {
    let yaml: serde_json::Value = serde_yaml::from_str(r#"null: "hello""#).unwrap();
    let json_str = serde_json::to_string(&yaml).unwrap();
    println!("{json_str}");
}

output:

{"null":"hello"}

Playground

cafce25
  • 15,907
  • 4
  • 25
  • 31
  • Wow, that is neat! But in that case a cannot do `apply_merge` https://docs.rs/serde_yaml/latest/serde_yaml/enum.Value.html#method.apply_merge there are such parts in my YAML as well ._. – yumaa Mar 21 '23 at 15:53
  • But you hinted me other solution: after performing `apply_merge`, firstly convert `serde_yaml::Value` to string via `serde_yaml::to_string(&yaml)` and then convert it back to `serde_json::Value` via `serde_yaml::from_str(&yaml_str)` :) Don't like double conversion though, but is is better, than manual recursion, I guess... – yumaa Mar 21 '23 at 16:24
  • `serde_json::to_value(&yaml)` might be more useful than `to_string` to you. – Caesar Mar 22 '23 at 00:20
  • Nope :( `serde_json::to_value(&yaml)` chokes on `null` keys too – yumaa Mar 22 '23 at 10:54