dtolnay / serde-yaml

Strongly typed YAML library for Rust
Apache License 2.0
964 stars 164 forks source link

Nested Enums? #363

Closed max-sixty closed 1 year ago

max-sixty commented 1 year ago

We're great fans of serde, great fans of YAML — thank you very much for the library.

Is there any workaround to the Error("serializing nested enums in YAML is not supported yet")? We're tried removing nested enums from our AST, but aren't able to do this fully (https://github.com/PRQL/prql/pull/2172#issuecomment-1478275290). We'd really like to represent our AST in something less verbose than JSON for human readability.

I've tried various incarnations of https://serde.rs/enum-representations.html, but not yet successfully.

Thanks a lot...

dtolnay commented 1 year ago

You could try using https://docs.rs/serde_yaml/0.9/serde_yaml/with/singleton_map which does not have that limitation.

use serde::{Serialize, Serializer};

#[derive(Serialize)]
#[serde(remote = "Self")]
pub enum ExprKind {
    ...
}

impl Serialize for ExprKind {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        struct ExternallyTaggedExprKind<'a>(&'a ExprKind);
        impl<'a> Serialize for ExternallyTaggedExprKind<'a> {
            fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
                ExprKind::serialize(self.0, serializer)
            }
        }
        serde_yaml::with::singleton_map::serialize(&ExternallyTaggedExprKind(self), serializer)
    }
}
max-sixty commented 1 year ago

Thank you very much! I did this in https://github.com/PRQL/prql/pull/2277 (I used just the derive approach from the docs, which seems to work well)

Fine to close!

replicadse commented 1 year ago

Not trying to open up old questions but when you're here and you are looking for this just as I just did (for the second or third time lol):

Check out the recursive version that allows Enums in HashMap, Vec etc. etc.: https://docs.rs/serde_yaml/latest/serde_yaml/with/singleton_map_recursive/index.html

I'll just leave that here with greeting to future people (and me) who are googling a similar thing and finding this exact issue.