GithubHelp home page GithubHelp logo

Comments (6)

jonasbb avatar jonasbb commented on May 18, 2024

Hi, thanks for the interest in this project. The function fits the scope of this project and could be added.

However, it seems your example does not what you intend it to do:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bec97a5a7ea17fc21ba46af3e80d1453

Do you have another use-case for this function or an alternative implementation?

from serde_with.

lovasoa avatar lovasoa commented on May 18, 2024

The function does work as expected. I'm not sure I understand what you are trying to do in the playground example. If you are trying to deserialize a list of strings, you don't need deserialize_ignore_any at all. It is helpful in cases like this, for example: RReverser/serde-xml-rs#55 (comment)

from serde_with.

jonasbb avatar jonasbb commented on May 18, 2024

#[serde(other)] declares an enum variant as fallback. "Ba" does not deserialize to any enum variant so in the playground it falls back to Other. However, if I add the deserialize_with attribute I get this error while deserializing: Err(Error("invalid type: unit variant, expected newtype variant", line: 0, column: 0)). The code deserializes the correct enum variant if you change "Ba" to "Foo", "Bar", or "Baz".

I will check the serde-xml link later.

from serde_with.

lovasoa avatar lovasoa commented on May 18, 2024

Ok, I understand what you were trying to do. Indeed, deserialize_ignore_any does not work in that case, because deserialize_with hints serde that you are trying to deserialize the contents of the enum variant, and the string is the enum variant, but does not have any contents. If you want an example where using deserialize_ignore_any may be useful in serde_json, you can add #[serde(untagged)] to your enum, and remove #[serde(other)]:

use serde::*;

fn main() {
    println!("{:?}", serde_json::from_str::<Vec<Item>>(r#"[{"y":1}, {"x":1}]"#));
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum Item {
    Foo{x: u8},
    #[serde(deserialize_with = "deserialize_ignore_any")]
    Other,
}

fn deserialize_ignore_any<'de, D: Deserializer<'de>, T:Default>(deserializer: D) -> Result<T, D::Error> {
    serde::de::IgnoredAny::deserialize(deserializer).map(|_| T::default())
}

playground

from serde_with.

jonasbb avatar jonasbb commented on May 18, 2024

Ok I think I understand now how this can be used.

  1. It enabled the other variant in an enum (tagged with #[serde(other)] to consume data without failing the deserialization. This "breaks" deserialization of data-less enums (the "Ba" example above).
  2. You can create an other-like enum variant in an untagged enum, which does not allow the #[serde(other)] attribute. It behaves similar to Other(serde::de::IgnoredAny), but without the downside of including the IgnoredAny type.

@lovasoa Do you want to create a pull request to add the method? It probably fits best in src/rust.rs.

Is it possible to extend the method to support enums with and without data? Basically supporting this without any errors during deserialization.

use serde::*;

fn main() {
    println!("{:?}", serde_json::from_str::<Vec<Item>>(r#"[{"NotFoo": {"y":1}}, {"Foo": {"x":1}}, "NotBar", "Bar"]"#));
}

#[derive(Debug, Deserialize)]
enum Item {
    Bar,
    Foo{x: u8},
    #[serde(other)]
    #[serde(deserialize_with = "deserialize_ignore_any")]
    Other,
}

fn deserialize_ignore_any<'de, D: Deserializer<'de>, T:Default>(deserializer: D) -> Result<T, D::Error> {
    serde::de::IgnoredAny::deserialize(deserializer).map(|_| T::default())
}

from serde_with.

lovasoa avatar lovasoa commented on May 18, 2024

Is it possible to extend the method to support enums with and without data?

I don't think so, no. Serde will not even call the method when deserializing a string value for the enum. It will see that the code is expecting contents inside the enum variant, and that the data doesn't have it. What you can do in this case is :

#[derive(Debug, Deserialize)]
enum Item {
    Bar,
    Foo{x: u8},
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum ItemContainer {
    Item(Item),
    #[serde(deserialize_with = "deserialize_ignore_any")]
    Other,
}

I do admit that the usefulness is more limited with serde_json than with, for instance, serde-xml-rs, where #[serde(other, deserialize_with = "deserialize_ignore_any")] is the only way of parsing a heterogeneous collection without knowing the shape of all objects in the collection.

from serde_with.

Related Issues (20)

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.