Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error "bad namespace for Body, found http://schemas.xmlsoap.org/soap/envelope/" #177

Open
averichev opened this issue Feb 9, 2024 · 4 comments

Comments

@averichev
Copy link

Error on deserialize

use yaserde_derive::{YaDeserialize, YaSerialize};

#[test]
fn basic() {
    #[derive(YaDeserialize, YaSerialize)]
    #[yaserde(
    prefix = "soap",
    namespace="soap: http://schemas.xmlsoap.org/soap/envelope/"
    )]
    pub struct Envelope {
        #[yaserde(prefix="soap", rename="Body")]
        pub body: BodyEnum,
    }

    #[derive(YaDeserialize, YaSerialize)]
    #[yaserde(flatten)]
    pub enum BodyEnum {
        #[yaserde(rename="Fault", prefix="soap")]
        #[yaserde(flatten)]
        Fault(Fault),
        #[yaserde(rename="GetMessageResponse" prefix="soap")]
        #[yaserde(flatten)]
        GetMessageResponse(GetMessageResponse),
    }

    impl Default for BodyEnum {
        fn default() -> Self {
            BodyEnum::Fault(Fault{ faultcode: "unknown code".to_string(), faultstring: "unknown fault".to_string() })
        }
    }

    #[derive(YaDeserialize, YaSerialize)]
    pub struct Fault {
        pub faultcode: String,
        pub faultstring: String
    }

    #[derive(YaDeserialize, YaSerialize)]
    pub struct GetMessageResponse {
        #[yaserde(prefix="ns", rename="Message")]
        pub message: Message,
    }

    #[derive(YaDeserialize, YaSerialize)]
    pub struct Message {
        #[yaserde(rename="AuthResponse", prefix="tns")]
        pub auth_response: AuthResponse,
    }

    #[derive(YaDeserialize, YaSerialize)]
    #[yaserde(
    namespace = "tns: urn://test/types/1.0"
    )]
    pub struct AuthResponse {
        #[yaserde(prefix="tns", rename="Result")]
        pub auth_app_info: Result,
    }

    #[derive(YaDeserialize, YaSerialize)]
    pub struct Result {
        #[yaserde(prefix="tns", rename="Token")]
        pub token: String,
        #[yaserde(prefix="tns", rename="expire")]
        pub expire: String,
    }

    let content = r#"
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <soap:Fault>
            <faultcode>soap:Server</faultcode>
            <faultstring>error description</faultstring>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>
"#;

    let envelope = yaserde::de::from_str::<Envelope>(&content).unwrap();
    match envelope.body {
        BodyEnum::Fault(_) => {}
        BodyEnum::GetMessageResponse(_) => {}
    }
}

Link to test

Is this my mistake in using the library or a bug?

@MarcAntoine-Arnaud
Copy link
Contributor

Hello @averichev ,

Sorry for the delay.
Can you try to rewrote:

    #[derive(YaDeserialize, YaSerialize)]
    #[yaserde(flatten)]
    pub enum BodyEnum {
        #[yaserde(rename="Fault", prefix="soap", flatten)]
        Fault(Fault),
        #[yaserde(rename="GetMessageResponse", prefix="soap", flatten)]
        GetMessageResponse(GetMessageResponse),
    }

I'm not sure the library handle multi #[yaserde scope.
In addition you've missed one comma after #[yaserde(rename="GetMessageResponse".

And if you get against an error, then it's mostly a bug on namespace with enums.

Best,
Marc-Antoine

@mtorromeo
Copy link

mtorromeo commented Sep 11, 2024

I think I am having the same issue. I tried to produce a minimal example:

use yaserde::*;

#[derive(YaDeserialize, Debug, PartialEq)]
#[yaserde(
  rename = "base",
  namespace = "http://base/",
  namespace = "ns1: http://ns1/",
  namespace = "ns2: http://ns2/"
)]
pub struct Base {
  #[yaserde(rename = "data", prefix = "ns1")]
  pub data: Ns2DataItemType,
}

#[derive(YaDeserialize, Debug, PartialEq, Default)]
#[yaserde(prefix = "ns2", namespace = "ns2: http://ns2/")]
pub enum Ns2DataItemType {
  #[yaserde(rename = "dataItem", prefix = "ns2")]
  DataItem(String),
  #[default]
  #[allow(non_camel_case_types)]
  __undefined__,
}

#[test]
fn mixed_namespaces() {
  use yaserde::de::from_str;

  let content = r#"
    <base
        xmlns="http://base/"
        xmlns:ns1="http://ns1/"
        xmlns:ns2="http://ns2/">
      <ns1:data>
        <ns2:dataItem>value1</ns2:dataItem>
      </ns1:data>
    </base>
  "#;

  let loaded: Base = from_str(content).unwrap();
  println!("{:?}", loaded);

  let reference = Base {
    data: Ns2DataItemType::DataItem("value1".to_string()),
  };

  assert_eq!(loaded, reference);
}

This results in

thread 'mixed_namespaces::mixed_namespaces' panicked at examples/src/mixed_namespaces.rs:40:40:
called `Result::unwrap()` on an `Err` value: "bad namespace for data, found http://ns1/"

Edit: reduced example

@mtorromeo
Copy link

mtorromeo commented Sep 11, 2024

To double check that I wasn't misusing the library I tried to serialize Base to string ser::to_string(&reference).unwrap() and the result seems correct:

<?xml version="1.0" encoding="utf-8"?><base xmlns="http://base/" xmlns:ns1="http://ns1/" xmlns:ns2="http://ns2/"><ns1:data><ns2:dataItem>value1</ns2:dataItem></ns1:data></base>

@mtorromeo
Copy link

I could work-around the issue by removing the namespace matching for the enum as it doesn't seem to affect the deserialization result in any way and is just there to provide the error "bad namespace for ...".

Specifically I commented out this line

#namespaces_matching

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants