I'm trying to parse xml response containing boolean representation as strings into bool type in a custom structure. A similar question was mentioned here for json files. And I get a runtime error that I suspect is just like the one mentioned here, but I don't know how I can fix it.
MRE:
[package]
name = "test_range_2"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0.147", features = ["derive"] }
serde-xml-rs = "0.6.0"
// main.rs
use serde::Deserialize;
fn deserialize_bool<'de, D>(deserializer: D) -> Result<bool, D::Error>
where
D: serde::de::Deserializer<'de>,
{
let s: &str = serde::de::Deserialize::deserialize(deserializer)?;
match s {
"TRUE" => Ok(true),
"FALSE" => Ok(false),
_ => Err(serde::de::Error::unknown_variant(s, &["TRUE", "FALSE"])),
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
struct Custom {
#[serde(deserialize_with = "deserialize_bool")]
tag1: bool,
#[serde(deserialize_with = "deserialize_bool")]
tag2: bool,
}
fn main() {
let xml_raw = r#"
<?xml version="1.0"?>
<Custom>
<tag1>TRUE</tag1>
<tag2>FALSE</tag2>
</Custom>
"#;
let events = serde_xml_rs::from_str::<Custom>(xml_raw)
.expect("unable to deserialize xml into Custom struct");
println!("{:#?}", events);
}
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/test_range_2`
thread 'main' panicked at 'unable to deserialize xml into Custom struct: Custom { field: "invalid type: string \"TRUE\", expected a borrowed string" }', src/main.rs:35:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Related links:
The error message here is useful
"invalid type: string "TRUE", expected a borrowed string"
You are trying to deserialize the string value as a &str
instead of a String
. This might be weirdness in the serde_xml_rs library but changing it to String lets it run as expected.
fn deserialize_bool<'de, D>(deserializer: D) -> Result<bool, D::Error>
where
D: serde::de::Deserializer<'de>,
{
let s: String = serde::de::Deserialize::deserialize(deserializer)?;
match s.as_str() { // note change here
"TRUE" => Ok(true),
"FALSE" => Ok(false),
_ => Err(serde::de::Error::unknown_variant(&s, &["TRUE", "FALSE"])), // and borrow here
}
}