如何 return 包含 serde_json::Value 的结果?

How to return a Result containing a serde_json::Value?

这就是我所拥有的,但我想避免在我的 reqwest 值上使用 unwrap

extern crate base64;
extern crate reqwest;

use serde_json;

use serde_json::json;

pub fn perform_get(id: String) -> serde_json::value::Value {
    let client = reqwest::Client::builder().build().unwrap();

    let url = String::from("SomeURL");

    let res = client.get(&url).send().unwrap().text();

    let mut v = json!(null);
    match res {
        Ok(n) => {
            v = serde_json::from_str(&n).unwrap();
        }
        Err(r) => {
            println!("Something wrong happened {:?}", r);
        }
    }

    v
}

fn main() {
    println!("Hi there! i want the function above to return a result instead of a Serde value so I can handle the error in main!");
}

Here is a link to a rust playground example

Rust 官方书籍 The Rust Programming Language, is freely available online. It has an entire chapter on using Result,解释了诸如 Result 枚举之类的介绍性主题及其使用方法。

How to return a Result containing a serde_json::Value?

与您 return 类型 anyResult 相同; Value:

没什么特别的
use serde_json::json; // 1.0.38

pub fn ok_example() -> Result<serde_json::value::Value, i32> {
    Ok(json! { "success" })
}

pub fn err_example() -> Result<serde_json::value::Value, i32> {
    Err(42)
}

如果您有一个 return 是 Result 的函数,您可以使用问号运算符 (?) 提前退出出错的函数,return 错误。这是避免 unwrapexpect:

的简洁方法
fn use_them() -> Result<(), i32> {
    let ok = ok_example()?;
    println!("{:?}", ok);

    let err = err_example()?;
    println!("{:?}", err); // Never executed, we always exit due to the `?`

    Ok(()) // Never executed
}

这只是一个基本示例。

应用于您的 MCVE,它看起来像:

use reqwest; // 0.9.10
use serde_json::Value; // 1.0.38

type Error = Box<dyn std::error::Error>;

pub fn perform_get(_id: String) -> Result<Value, Error> {
    let client = reqwest::Client::builder().build()?;

    let url = String::from("SomeURL");

    let res = client.get(&url).send()?.text()?;

    let v = serde_json::from_str(&res)?;

    Ok(v)
}

在这里,我使用 trait 对象 Box<dyn std::error::Error> 来处理任何类型的错误(非常适合快速程序和示例)。然后,我将 ? 洒在每个可能失败的方法上(即 returns a Result),并以明确的 Ok 作为最终值结束函数。

请注意,panic 和从未使用过的 null 值可以使用此样式删除。

另请参阅:

better practice to return a Result

另请参阅:

Rust Discord 的好心人帮我解决了这个问题。 (用户编号)

extern crate base64;
extern crate reqwest;

pub fn get_jira_ticket() -> Result<serde_json::value::Value, reqwest::Error> {
    let client = reqwest::Client::builder().build().unwrap();

    let url = String::from("SomeURL");

    let res = client.get(&url).send().and_then(|mut r| r.json());

    res
}

fn main() {
    println!("This works");
}

header 中的关键部分是 return

-> Result<serde_json::value::Value, reqwest::Error>

这里实际上是 return 数据。

client.get(&url).send().and_then(|mut r| r.json());

如果你在用户端我建议使用Box<dyn std::error::Error>, this allow to return every type that implement Error?会将具体错误类型转换为动态装箱特征,这会在出现错误时增加一些开销但是当错误不是预期的或非常罕见时,这没什么大不了的。

use reqwest;

use serde_json::value::Value;
use std::error::Error;

fn perform_get(_id: String) -> Result<Value, Box<dyn Error>> {
    let client = reqwest::Client::builder().build()?;

    let url = String::from("SomeURL");

    let res = client.get(&url).send()?.text()?;

    let v = serde_json::from_str(&res)?;

    Ok(v)

    // last two line could be serde_json::from_str(&res).map_err(std::convert::Into::into)
}

fn main() {
    println!("{:?}", perform_get("hello".to_string()));
}

这会产生以下错误:

Err(Error { kind: Url(RelativeUrlWithoutBase), url: None })