quick-xml icon indicating copy to clipboard operation
quick-xml copied to clipboard

Deserializing to variant vector fields fails

Open MoSal opened this issue 4 years ago • 4 comments

Example with tagged and untagged enums showing different errors. The tagged error seems to point to the source of the issue.

use serde::Deserialize;

fn main() {
    // struct

    let bs = br##"<Xs><st><v s="some_s"/></st></Xs>"##;

    // works as expected with 0, 1, or more `v` elements
    let xs: Xs = quick_xml::de::from_reader(&bs[..]).unwrap();
    eprintln!("{:#?}", xs);

    // tagged enum

    // no v, works
    let bn = br##"
        <XEnumWithTag>
          <en type="V">
          </en>
        </XEnumWithTag>
    "##;
    let xn: XEnumWithTag = quick_xml::de::from_reader(&bn[..]).unwrap();
    eprintln!("{:#?}", xn);

    // 1 v or more, fails with: "invalid type: map, expected a sequence"
    let bn = br##"
        <XEnumWithTag>
          <en type="V">
            <v s="some_s"/>
          </en>
        </XEnumWithTag>
    "##;
    let xn_res: Result<XEnumWithTag, _> = quick_xml::de::from_reader(&bn[..]);
    match xn_res {
        Ok(xn) => eprintln!("{:#?}", xn),
        Err(e)   => eprintln!("XEnumWithTag failed to deserialize: {:?}", e),
    }

    // same story with untagged, just different error

    // no v, works
    let bn = br##"
        <XEnumUntagged>
          <en>
          </en>
        </XEnumUntagged>
    "##;
    let xn: XEnumUntagged = quick_xml::de::from_reader(&bn[..]).unwrap();
    eprintln!("{:#?}", xn);

    // 1 v or more, fails with: "data did not match any variant of untagged enum EnumUntagged"
    let bn = br##"
        <XEnumUntagged>
          <en>
            <v s="some_s"/>
          </en>
        </XEnumUntagged>
    "##;
    let xn_res: Result<XEnumUntagged, _> = quick_xml::de::from_reader(&bn[..]);
    match xn_res {
        Ok(xn) => eprintln!("{:#?}", xn),
        Err(e)   => eprintln!("XEnumUntagged failed to deserialize: {:?}", e),
    }
}

#[derive(Deserialize, Debug)]
struct SWrap {
    s: String,
}

#[derive(Deserialize, Debug)]
#[serde(tag="type")]
enum EnumWithTag {
    S{ s: String },
    V{
        //v: Option<SWrap>, // works
        //v: Vec<SWrap>, // fails
        v: Option<Vec<SWrap>>, // fails if not None
    },
}

#[derive(Deserialize, Debug)]
#[serde(untagged)]
enum EnumUntagged {
    S{ s: String },
    V{
        v: Option<Vec<SWrap>>, // fails if not None
    },
}

#[derive(Deserialize, Debug)]
struct St {
    v: Option<Vec<SWrap>>, // works
}

#[derive(Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct Xs {
    st: Option<St>,
}

#[derive(Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct XEnumWithTag {
    en: Option<EnumWithTag>,
}

#[derive(Deserialize, Debug)]
#[serde(deny_unknown_fields)]
pub struct XEnumUntagged {
    en: Option<EnumUntagged>,
}

MoSal avatar May 31 '21 03:05 MoSal

I hit this error as well. I added a test case (de::tests::enum_::internally_tagged::collection_struct::attributes) in the vec-invariant branch on my fork.

It fails with:

---- de::tests::enum_::internally_tagged::collection_struct::attributes stdout ----
thread 'de::tests::enum_::internally_tagged::collection_struct::attributes' panicked at 'called `Result::unwrap()` on an `Err` value: Custom("invalid type: map, expected a sequence")', src/de/mod.rs:1184:26

cpick avatar Jul 19 '21 00:07 cpick

I correctly understand, that #387 addresses those problems? If not, please try to reduce your example and turn it into the Rust testcase

Mingun avatar May 21 '22 20:05 Mingun