问题
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