media-io / yaserde

Yet Another Serializer/Deserializer
MIT License
182 stars 63 forks source link

Prefix sometimes not working while deserializing #202

Open Rex-Sanchez opened 5 days ago

Rex-Sanchez commented 5 days ago

Im having trouble deserializing with prefixes

#[derive(YaSerialize, YaDeserialize, Debug, Default, Clone, Eq, PartialEq)]
pub struct Header {}

#[derive(YaSerialize, YaDeserialize, Debug, Default, Clone, Eq, PartialEq)]
#[yaserde(
  rename = "Envelope",
  namespaces = {
    "soapenv" = "http://schemas.xmlsoap.org/soap/envelope/",
  },
  prefix = "soapenv"
)]
pub struct SoapEnvelope<BODY>
where
    BODY: YaSerialize + YaDeserialize + Default,
{
    #[yaserde(rename = "Header", prefix = "soapenv")]
    pub header: Option<Header>,
    #[yaserde(rename = "Body", prefix = "soapenv")]
    pub body: BODY,
}

#[derive(YaSerialize, YaDeserialize, Debug, Default, Clone, Eq, PartialEq)]
struct Body {
    #[yaserde(prefix = "urn")]
    text: String,
}

serializing the following:

let b = Body {
        text: "hello world".to_string(),
    };
let env = SoapEnvelope {
        body: b,
        ..Default::default()
    };

let s = yaserde::ser::to_string(&env).unwrap();

dbg!(s);

this yields:

"<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope" >
<soapenv:Body>
<urn:text>hello world</urn:text>
</soapenv:Body>
</soapenv:Envelope>

the text elements is serialized with the prefix

 let envelope = yaserde::de::from_str::<SoapEnvelope<Body>>(&s).unwrap();

this now errors with value: "text is a required field of Body"

when the prefix is removed from the text element it will serialize without a problem

"<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope" >
<soapenv:Body>
<text>hello world</text>
</soapenv:Body>
</soapenv:Envelope>

if this xml is deserialized with the urn prefix on the text element. the prefix is ignored and the xml is deserialized without error.. so it seems that the deserializer is ignoring the prefix.

MarcAntoine-Arnaud commented 5 days ago

Can you test with a valid struct ? The urn is a prefix, but no namespace is declared.

#[derive(YaSerialize, YaDeserialize, Debug, Default, Clone, Eq, PartialEq)]
#[yaserde(
  namespaces = {
    "urn" = "http://example.com/",
  }
)]
struct Body {
    #[yaserde(prefix = "urn")]
    text: String,
}
Rex-Sanchez commented 4 days ago

Good day.. thx for the response..

im not sure what you mean by valid struct.. when i declare it with a namespace like above it does work but body should not have a namespace.. as in the thing im serialize and deserialize does not have a namespace on the body. as a example what im trying to serialize and deserialize

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:something"  >
   <soapenv:Header/>
   <soapenv:Body>
      <urn:getProducts>
         <urn:manyfields>data in field</urn:manyfields>
      </urn:getProducts>
   </soapenv:Body>
</soapenv:Envelope>

as you can see there is no namespace one body, while the nested elements do have a prefix.

im am using 2 namespaces on the envelope like the following

#[derive(YaSerialize, YaDeserialize, Debug, Default, Clone, Eq, PartialEq)]
#[yaserde(
  rename = "Envelope",
  namespaces = {
    "soapenv" = "http://schemas.xmlsoap.org/soap/envelope/",
    "urn" = "urn:something"
  },
  prefix = "soapenv"
)]
pub struct SoapEnvelope<BODY>
MarcAntoine-Arnaud commented 1 day ago

The main issue is the miss of the declaration of "urn" = "urn:something" Without that, no namespace prefix urn is declared, so it cannot be handled correctly.