How to set desired return type in match structure?

帅比萌擦擦* 提交于 2021-01-07 02:09:34

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!