Code Monkey home page Code Monkey logo

Comments (9)

kornelski avatar kornelski commented on May 28, 2024 2

For the record, I've managed to implement it "the hard way" like this:

impl<'de> Deserialize<'de> for MyEnum {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>,
    {
        struct MyEnumVisitor;

        impl<'a> Visitor<'a> for MyEnumVisitor {
            type Value = MyEnum;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a or b")
            }

            fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
                match v.to_lowercase().as_str() {
                    "variant_a" => Ok(MyEnum::A),
                    "variant_b" => Ok(MyEnum::B)
                    x => Err(de::Error::unknown_variant(x, &["a", "b"])),
                }
            }

            fn visit_string<E: de::Error>(self, v: String) -> Result<Self::Value, E> {
                self.visit_str(&v)
            }
        }

        deserializer.deserialize_string(MyEnumVisitor)
    }
}

from serde-aux.

mainrs avatar mainrs commented on May 28, 2024 2

Thanks for taking your time! In my use-case right now, it is actually for the deserialize_struct_case_insensitive. I have a simple enum with variants that do not hold any additional data and want it to, well, be deserializable, independent of the string's case :)

Maybe something like deserialize_plain_enum_case_insensitive is a good fit. Maybe there is even an official name for these enums:

enum E {
 A, B, C, D
}

As of know, I just implemented the deserialization myself, the same way as @kornelski did above.

from serde-aux.

mainrs avatar mainrs commented on May 28, 2024 1

@vityafx:
What if an enum must implement FromStr + Deserialize, and the FromStr implementation will be used to do a lowercase comparison. Maybe having the end-user depend on strum_macros to implement the FromStr might be a good idea. Not sure if this approach works in serde as I am not familiar with the internals to be honest.

from serde-aux.

iddm avatar iddm commented on May 28, 2024 1

Of course, this will work, and I could have implemented it myself, but this is not a generic solution I am looking for. For example, such a way still won't allow such an enum to be deserialized:

enum A {
    A,
    B(u64)
    C(Box<A>),
    D(Vector<A>),
    // and all other "complex" varieties
}

If you look at the syn parser, the enums are always complex, and such enums will require hell ton of a work to specify all the possible ways of deserialisation. It may work, but then it won't work for the types which aren't just plain enums in C/C++ meaning. Perhaps, it can't be done at all.

As you and other people are looking forward to seeing the support of this macro even for plain enums, I will add it, but under a different name. I might need a couple of weeks, can't return to this project right now, unfortunately. Perhaps, I will take a look at it even sooner. So stay tuned. :)

And thanks for bringing this up, as I don't know how this crate is used, I only see it is a bit popular, but whenever I try to look at its' usage through going each dependent crate, it is quite poor, like only "deserialise_bool_from_anything" is used :) So if you have any other suggestions, please post those! Have a nice day!

from serde-aux.

iddm avatar iddm commented on May 28, 2024

Yes, I know that. This is intentional. I did not have much time to think how to do this for enums also unfortunately.

from serde-aux.

iddm avatar iddm commented on May 28, 2024

Awesome! Perhaps we could use it :) I'll look what we can do some time later, not sure when. It looks it is not so difficult though. Thank you for posting your hardcoded solution, it is useful anyway.

from serde-aux.

iddm avatar iddm commented on May 28, 2024

I've just checked again and I don't think I may come up with a generic solution. Custom deserialisation will always work (at least it should), but can't think of something generic here. Also, enums are different and so the deserialisation must be different for all the types of enums.

from serde-aux.

yanns avatar yanns commented on May 28, 2024

For info, I've found a more generic way to ignore the case when deserializing enums with variants that do not hold any additional data: https://docs.rs/oauth2/latest/oauth2/helpers/fn.deserialize_untagged_enum_case_insensitive.html#
You can have a look at the source to see how it is implemented:

///
/// Serde case-insensitive deserializer for an untagged `enum`.
///
/// This function converts values to lowercase before deserializing as the `enum`. Requires the
/// `#[serde(rename_all = "lowercase")]` attribute to be set on the `enum`.
///
/// # Example
///
/// In example below, the following JSON values all deserialize to
/// `GroceryBasket { fruit_item: Fruit::Banana }`:
///
///  * `{"fruit_item": "banana"}`
///  * `{"fruit_item": "BANANA"}`
///  * `{"fruit_item": "Banana"}`
///
/// Note: this example does not compile automatically due to
/// [Rust issue #29286](https://github.com/rust-lang/rust/issues/29286).
///
/// ```
/// # /*
/// use serde::Deserialize;
///
/// #[derive(Deserialize)]
/// #[serde(rename_all = "lowercase")]
/// enum Fruit {
///     Apple,
///     Banana,
///     Orange,
/// }
///
/// #[derive(Deserialize)]
/// struct GroceryBasket {
///     #[serde(deserialize_with = "helpers::deserialize_untagged_enum_case_insensitive")]
///     fruit_item: Fruit,
/// }
/// # */
/// ```
///
pub fn deserialize_untagged_enum_case_insensitive<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: Deserialize<'de>,
    D: Deserializer<'de>,
{
    use serde::de::Error;
    use serde_json::Value;
    T::deserialize(Value::String(
        String::deserialize(deserializer)?.to_lowercase(),
    ))
    .map_err(Error::custom)
}

What do you think about having this generic function in serde-aux ?

from serde-aux.

iddm avatar iddm commented on May 28, 2024

I think it is already better to implement a proc-macro for that and use an attribute, and correctly, using the syn crate, generate the deserializing code. Or, perhaps, just a macro.

from serde-aux.

Related Issues (16)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.