问题
In the example in the crate documentation of serde_json (parse JSON into a Rust struct), error handling is omitted:
use serde::{Deserialize, Serialize};
use serde_json::Result;
#[derive(Serialize, Deserialize)]
struct Person {
name: String,
age: u8,
phones: Vec<String>,
}
fn typed_example() -> Result<()> {
// Some JSON input data as a &str. Maybe this comes from the user.
let data = r#"
{
"name": "John Doe",
"age": 43,
"phones": [
"+44 1234567",
"+44 2345678"
]
}"#;
// Parse the string of data into a Person object. This is exactly the
// same function as the one that produced serde_json::Value above, but
// now we are asking it for a Person as output.
let p: Person = serde_json::from_str(data)?;
// Do things just like with any other Rust data structure.
println!("Please call {} at the number {}", p.name, p.phones[0]);
Ok(())
}
What from_string() does is controlled by the type of the target of the assignment.
In practice, we have to handle the error. So, the natural thing to do is:
match p: Person = serde_json::from_str(data) {
// ...
}
but that is not allowed in match structure.
match serde_json::from_str(data) {
// ...
}
returns always an empty type "()".
My situation involves many nested match structures, so I would not like to use the obvious solution of assigning to a variable first.
How do I control the desired target type of expression in the match structure?
回答1:
In the example you give, error handling is deferred to the caller:
let p: Person = serde_json::from_str(data)?;
Notice the ? at the end: it means that in case of error, the function should return immediately propagating the error.
If you want to handle the error locally, you need to use match, but you can't do match p: Person = serde_json::from_str(data) { /* ... */ } because from_str doesn't return a Person. What you need to do is:
let p: Person = match serde_json::from_str (data) {
Ok (p) => p,
Err (_) => Person { name: "John Doe".into(), age: 42, phones: vec![] },
}
回答2:
As mentioned by Herohtar, the syntax match p: Person = serde_json::from_str(data) { /* ... */ } is invalid, but you can do
let p: Person = match serde_json::from_str(data) {
// ...
}
Another option is turbofish:
let p = match serde_json::from_str::<Person>(data) {
// ...
}
来源:https://stackoverflow.com/questions/60332602/how-to-set-desired-return-type-in-match-structure