Как вернуть результат, содержащий serde_json :: Value? - PullRequest
0 голосов
/ 03 апреля 2019

Это то, что у меня есть, но я хочу избегать использования unwrap в моих значениях reqwest:

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!");
}

Вот ссылка на пример ржавой игровой площадки

Ответы [ 3 ]

4 голосов
/ 03 апреля 2019

Официальная книга Rust, Язык программирования Rust , свободно доступна онлайн. В нем есть целая глава по использованию Result, в которой объясняются вводные темы, такие как перечисление Result и как его использовать.

Как вернуть Result, содержащий serde_json::Value?

Так же, как вы возвращаете Result типа любого ; в 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)
}

Если у вас есть функция, которая возвращает Result, вы можете использовать оператор вопросительного знака (?), чтобы досрочно выйти из функции при ошибке и вернуть ошибку. Это краткий способ избежать unwrap или expect:

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> для обработки любых ошибок (отлично подходит для быстрых программ и примеров). Затем я набрасываю ? на каждый метод, который может потерпеть неудачу (т.е. возвращает Result), и заканчиваю функцию явным Ok для окончательного значения.

Обратите внимание, что с помощью этого стиля можно удалить panic и никогда не использованное значение null.

Смотри также:

Лучше практиковать возвращение Result

Смотри также:

3 голосов
/ 03 апреля 2019

Если вы находитесь на стороне пользователя, я бы предложил использовать Box<dyn std::error::Error>, это позволит возвращать каждый тип, который реализует 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 })
0 голосов
/ 03 апреля 2019

Добрые умные люди из Rust Discord помогли мне решить эту проблему.(user noc)

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");
}

Ключевая часть была этой в заголовке для возврата

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

И это здесь, чтобы фактически вернуть данные.

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