Closed willfindlay closed 2 years ago
I'm wondering the same. Tags don't roundtrip cleanly to JSON, aren't compatible with the old format, and don't compose. They are also problematic for Kubernetes, which expects to be able to convert freely between JSON, YAML, and Protobuf.
For example, the following example runs fine with serde_yaml 0.8 but panics for 0.9:
use serde::Serialize;
#[derive(Serialize)]
enum Parent {
ParentVariant(Child),
}
#[derive(Serialize)]
enum Child {
ChildVariant(u8),
}
fn main() {
let value = Parent::ParentVariant(Child::ChildVariant(0));
println!("serde_yaml 0.8:");
println!("{}", serde_yaml08::to_string(&value).unwrap());
println!("serde_yaml 0.9:");
println!("{}", serde_yaml09::to_string(&value).unwrap());
}
You would need to use https://docs.rs/serde_yaml/0.9/serde_yaml/with/singleton_map/index.html on whichever field you want the opposite representation for.
Thanks for the workaround, @dtolnay! That worked for me :)
@dtolnay Follow-up question: What would be the easiest/best way to make this work with a Vec<T>
for example where T
is an untagged enum?
Also, wouldn't it have been better to make this new behaviour opt-in? To me, it feels like wanting to use !Tag
would be the exception rather than the rule considering so many use cases require compatibility with JSON.
@dtolnay Follow-up question: What would be the easiest/best way to make this work with a
Vec<T>
for example whereT
is an untagged enum?Also, wouldn't it have been better to make this new behaviour opt-in? To me, it feels like wanting to use
!Tag
would be the exception rather than the rule considering so many use cases require compatibility with JSON.
I second this. Could this be safely reverted?
Perhaps there should be some kind of settings struct that lets you choose how you want it to work?
Perhaps there should be some kind of settings struct that lets you choose how you want it to work?
Or maybe even just a feature flag 👀
A feature flag would be unwise. In a diamond dependency scenario, crates would change each other's format by setting that feature flag. serde_yaml would get compiled once, with the flag set, to be used by both its dependents.
Ah good point @divergentdave, makes sense.
You would need to use https://docs.rs/serde_yaml/0.9/serde_yaml/with/singleton_map/index.html on whichever field you want the opposite representation for.
This doesn't appear to work if you apply it to a struct with an Option<Enum>
; the with
attribute somehow wants to treat this as a non-optional and fails the parsing when the Option<Enum>
value is not included in the yaml
file. Perhaps I'm missing something?
This is stumbling me today, I want to generate some YAML for Github Actions "Workflow", the on:
field. Example:
on:
label:
types: [opened]
with
#[derive(Serialize, Deserialize)]
pub enum LabelTypes {
#[serde(rename = "opened")]
Opened,
#[serde(rename = "labeled")]
Labeled,
}
#[derive(Serialize, Deserialize)]
#[allow(non_camel_case_types)]
pub enum GHAEvent {
#[serde(rename = "push")]
Push,
#[serde(with = "serde_yaml::with::singleton_map")]
label { types: Vec<LabelTypes> },
}
With some extra weirdness to get the label not be uppercased "Label" but I'm still getting
on:
- !label
- opened
adding rename = "label"
to the serde annotation and leaving out the #[allow(non_camel_case_types)]
still leaves me with a tagged !label
list. I'm ignoring the inline vs. lined rendering since they mean the same thing.
Round tripping from YAML->Serde would be nice, but I'm not expecting it, I'm more focused on typed checked data structures doing the work and serde_yaml writing the YAML for me.
I know this issue is closed already, but for anyone coming across and looking for the answer on this:
What would be the easiest/best way to make this work with a
Vec<T>
for example whereT
is an untagged enum?
Apparently the solution is to use #[serde(with = "serde_yaml::with::singleton_map_recursive")]
(note the _recursive
part). With this, all the nested types will use the singleton map approach.
And re: this:
Also, wouldn't it have been better to make this new behaviour opt-in? To me, it feels like wanting to use
!Tag
would be the exception rather than the rule considering so many use cases require compatibility with JSON.
Definitely agree with that, because:
So bottom line, we replace a good working solution with a half-broken one, and make it a default, without even clear docs on how to get the old behavior (Imo the release notes should at the very least clarify it in detail, with all those attributes; it took me a while to find out the right attribute). Overall, this seems like a bad call to me. Alas.
Hi, I was wondering if there is a way (besides just not upgrading the crate version) to opt out of the
!Tag
syntax for enums and keep the old behaviour?