jonasbb / serde_with

This crate provides custom de/serialization helpers to use in combination with serde's `with`-annotation and with the improved `serde_as`-annotation.
https://docs.rs/serde_with
Apache License 2.0
636 stars 67 forks source link

OneOrMany serialization not implemented? #728

Closed adwhit closed 4 months ago

adwhit commented 5 months ago

Hi, thanks for the great crate, I use it all the time.

The docs seems to suggest that OneOrMany will serialize a Vec as a singleton or list depending upon config. There is even a helpful example. However the example does not actually demo serialization and in face serialization does not actually work. Inspecting the generated code with cargo expand, it seems to do nothing at all.

Repro:

    #[test]
    fn test_serde_one_many() {
        use serde_with::{serde_as, OneOrMany};

        #[serde_as]
        #[derive(serde::Deserialize, serde::Serialize)]
        struct Data {
            #[serde_as(deserialize_as = "OneOrMany<_>")]
            countries: Vec<AssetId>,
        }
        let data = Data {
            countries: vec!["Spain".to_string().into()],
        };
        let expect = serde_json::json!({
            "countries": "Spain",
        });
        assert_eq!(serde_json::to_value(data).unwrap(), expect);
    }
adwhit commented 5 months ago

OK, I realized this is just a docs issue. If we change the annotation to

#[serde_as(deserialize_as = "OneOrMany<_>", serialize_as = "OneOrMany<_>")]

it works correctly.

jonasbb commented 4 months ago

In your first post you only specify deserialize_as. This means you are requesting the logic to only run during deserialization. If you want to run during serialization too, just use as or combine serialize_as and deserialize_as like your second post. You can even specify how you want single elements to be serialized with PreferOne or PreferMany.

adwhit commented 4 months ago

I appreciate that I was using it wrong. As I mentioned in my second comment, its because the docs are wrong or at least misleading - see https://docs.rs/serde_with/latest/serde_with/struct.OneOrMany.html. They don't specify to use serialize_as, and the example seems to suggest that it demonstrates serialization but in fact only shows deserialization. So probably the example should be updated.

jonasbb commented 4 months ago

Yes indeed. I update the doctest to ensure serialization is tested and align it more with the other examples.