如果您曾经使用过serde或serde-xml-rs,那么您一定见过the sample code。他们的所有示例代码总是upwrap()s from_reader()函数调用。但是,如果我们需要像下面的扩展示例代码那样实际处理错误,会发生什么呢?
Cargo.toml
[package]
name = "so-help"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = "1.0.130"
serde_derive = "1.0.130"
serde-xml-rs = "0.5.0"src/main.rs
#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_xml_rs;
use serde_xml_rs::from_reader;
#[derive(Debug, Deserialize)]
struct Item {
pub name: String,
pub source: String
}
#[derive(Debug, Deserialize)]
struct Project {
pub name: String,
#[serde(rename = "Item", default)]
pub items: Vec<Item>
}
fn main() {
let correct = r##"
<Project name="my_project">
<Item name="hello" source="world.rs" />
</Project>
"##;
let project: Project = from_reader(correct.as_bytes()).unwrap();
println!("{:#?}", project);
let malformed = r##"
<Project name="malformed">
<malformed name="Hello" source="world.rs />
<WeDontClose This>
</Project>
"##;
let messedup: Project = from_reader(malformed.as_bytes()).unwrap();
println!("{:#?}", messedup);
}malformed变量包含格式错误的XML数据,这些数据会导致from_reader()返回错误,但是由于示例总是使用unwrap(),因此没有解释如何处理这种错误状态。所以当我们运行我们的代码时,我们得到...
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/so-help`
Project {
name: "my_project",
items: [
Item {
name: "hello",
source: "world.rs",
},
],
}
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Syntax { source: Error { pos: 4:13, kind: Syntax("Unexpected token inside attribute value: <") } }', src/main.rs:37:63
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace我想要做的是使用惯用的rust语义通过match语句来处理错误。所以我试着通过替换这一行来处理这个错误...
let messedup: Project = from_reader(malformed.as_bytes()).unwrap();..。用这些台词..。
let messedup: Project = match from_reader(malformed.as_bytes())
{
Ok(v) => v,
Err(e) => println!("Error reading malformed xml {:?}", e),
};..。但是我得到了这个编译时错误...
$ cargo run
Compiling so-help v0.1.0 (/home/dygear/so-help)
error[E0308]: mismatched types
--> src/main.rs:40:19
|
40 | Err(e) => println!("Error reading malformed xml {:?}", e),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Project`, found `()`
|
= note: this error originates in the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0308`.
error: could not compile `so-help` due to previous error那么我应该如何处理解析错误呢?我问过关于铁锈不和谐的问题,但似乎没有人对此有答案。问题似乎是由于使用的数据类型造成的,但我希望返回该数据类型,或者返回错误。
示例代码也是available on github的,因此您可以确切地看到我所在的位置
尝试@Lagerbaer的代码实际上并不起作用。
fn main() {
let correct = r##"
<Project name="my_project">
<Item name="hello" source="world.rs" />
</Project>
"##;
let project: Project = from_reader(correct.as_bytes()).unwrap();
println!("{:#?}", project);
let malformed = r##"
<Project name="malformed">
<malformed name="Hello" source="world.rs />
<WeDontClose This>
</Project>
"##;
let potentially_messed_up: Result<Project, serde_xml_rs::Error> = from_reader(malformed.as_bytes());
if let Err(e) = potentially_messed_up {
println!("Error reading malformed xml {:?}", e);
} else {
// now here we do stuff that we _only_ do if there's no error
potentially_messed_up.unwrap();
// here we can unwrap without ever causing a panic, because the
// if let Err(e) part made sure that we don't enter this branch if
// there was an error
}
println!("{:#?}", potentially_messed_up);
}产生以下错误:
error[E0282]: type annotations needed for `Result<T, serde_xml_rs::Error>`
--> src/main.rs:42:13
|
37 | let potentially_messed_up = from_reader(malformed.as_bytes());
| --------------------- consider giving `potentially_messed_up` the explicit type `Result<T, serde_xml_rs::Error>`, with the type parameters specified
...
42 | let v = potentially_messed_up.unwrap();
| ^ cannot infer type
error: aborting due to previous error所以我们现在把37行改成这样...
let potentially_messed_up: Result<Project, serde_xml_rs::Error> = from_reader(malformed.as_bytes());..。生成此错误...
error[E0382]: borrow of moved value: `potentially_messed_up`
--> src/main.rs:47:23
|
37 | let potentially_messed_up: Result<Project, serde_xml_rs::Error> = from_reader(malformed.as_bytes());
| --------------------- move occurs because `potentially_messed_up` has type `Result<Project, serde_xml_rs::Error>`, which does not implement the `Copy` trait
...
42 | potentially_messed_up.unwrap();
| -------- `potentially_messed_up` moved due to this method call
...
47 | println!("{:#?}", potentially_messed_up);
| ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
|
note: this function takes ownership of the receiver `self`, which moves `potentially_messed_up`
help: consider calling `.as_ref()` to borrow the type's contents
|
42 | potentially_messed_up.as_ref().unwrap();
| ^^^^^^^^^
error: aborting due to previous error所以我们改变这里的语句...
let potentially_messed_up: Result<Project, serde_xml_rs::Error> = from_reader(malformed.as_bytes());
if let Err(ref e) = potentially_messed_up {
println!("Error reading malformed xml {:?}", e);
} else {
// now here we do stuff that we _only_ do if there's no error
potentially_messed_up.as_ref().unwrap();
// here we can unwrap without ever causing a panic, because the
// if let Err(e) part made sure that we don't enter this branch if
// there was an error
}
println!("{:#?}", potentially_messed_up);在某种程度上是可行的,当存在时处理Err,但当没有时返回一个Ok包装的Project。这也不太正确。
Project {
name: "my_project",
items: [
Item {
name: "hello",
source: "world.rs",
},
],
}
Ok(
Project {
name: "my_project",
items: [
Item {
name: "hello",
source: "world.rs",
},
],
},
)@Jmb下面的评论包含了一个要点,我遵循这个要点是为了更接近惯用的锈蚀,但我似乎也不能让它起作用。它会处理格式错误的输入错误,也会在Err匹配臂中处理正确的输入。这很奇怪,因为它直接在上面被正确读取。
fn main() {
let correct = r##"
<Project name="my_project">
<Item name="hello" source="world.rs" />
</Project>
"##;
let project: Project = from_reader(correct.as_bytes()).unwrap();
println!("{:#?}", project);
let malformed = r##"
<Project name="malformed">
<malformed name="Hello" source="world.rs />
<WeDontClose This>
</Project>
"##;
let correct = r##"
<Project name="my_project">
<Item name="hello" source="world.rs" />
</Project>
"##;
let xml = match from_reader(correct.as_bytes())
{
Err (e) =>
{
println!("Error reading malformed xml {:?}", e);
return
}
Ok(xml) =>
{
xml
}
};
println!("{:?}", xml);
}warning: unused variable: `malformed`
--> src/main.rs:31:9
|
31 | let malformed = r##"
| ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_malformed`
|
= note: `#[warn(unused_variables)]` on by default
warning: 1 warning emitted
Finished dev [unoptimized + debuginfo] target(s) in 0.22s
Running `target/debug/so-help`
Project {
name: "my_project",
items: [
Item {
name: "hello",
source: "world.rs",
},
],
}
Error reading malformed xml UnexpectedToken { token: "&XmlEvent::EndElement { .. }", found: "StartElement(Item, {\"\": \"\", \"xml\": \"http://www.w3.org/XML/1998/namespace\", \"xmlns\": \"http://www.w3.org/2000/xmlns/\"}, [name -> hello, source -> world.rs])" }发布于 2021-09-09 17:26:45
我很惊讶你没有得到答案,因为它应该是相对简单的。
您的代码不能编译,因为您使用匹配表达式将值赋给类型为Project的变量,但只有一个匹配臂实际返回该类型的值,而另一个匹配臂不返回任何内容,它只是打印内容。
让我们放轻松,一步一步来。unwrap是Result枚举的一种方法,正如您所知道的,它的行为是,如果值存在,则只返回值,如果出现错误,则返回异常。
因此,如果我们删除unwrap,剩下的就是一个Result枚举。这就是您处理错误所需的全部内容,当然,现在您必须决定如何处理错误。在您的示例中,您将打印一条错误消息。但之后会发生什么呢?下面是你可以做的:
let potentially_messed_up = from_reader(malformed.as_byes());
if let Err(e) = potentially_messed_up {
println!("Error reading malformed xml {:?}", e);
} else {
// now here we do stuff that we _only_ do if there's no error
let v = potentially_messed_up.unwrap();
// here we can unwrap without ever causing a panic, because the
// if let Err(e) part made sure that we don't enter this branch if
// there was an error
}https://stackoverflow.com/questions/69122148
复制相似问题