Как я могу получить JSON из Github API?

Я просто хочу получить JSON по следующему URL-адресу.

Итак, я использовал этот код:

extern crate reqwest;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let res = reqwest::Client::new()
        .get("https://api.github.com/users/octocat")
        .send()?
        .text()?;
    println!("{}", res);

    Ok(())
}

Но я не знаю, как исправить ошибку:

error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try`
  --> src\main.rs:19:15
   |
19 |       let res = reqwest::Client::new()
   |  _______________^
20 | |         .get("https://api.github.com/users/octocat")
21 | |         .send()?
   | |________________^ the `?` operator cannot be applied to type `impl std::future::Future`
   |
   = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future`
   = note: required by `std::ops::Try::into_result`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `Desktop`.

но я также могу получить то, что хочу, с помощью простого

curl https://api.github.com/users/octocat

Пытался добавить use std::ops::Try;, но лучше не работает.


person Wolodia ZDETOVETZKY    schedule 03.11.2020    source источник
comment
Отвечает ли это на ваш вопрос? Как синхронно вернуть значение, вычисленное в асинхронном будущем в стабильном Rust?   -  person E_net4 the curator    schedule 03.11.2020
comment
Метод .send в этой версии reqwest является асинхронным. Он возвращает будущее, которое необходимо выполнить до завершения. См. Рабочий пример в документации по reqwest.   -  person E_net4 the curator    schedule 03.11.2020


Ответы (1)


reqwest crate по умолчанию поддерживает асинхронный API. Следовательно, вы должны .await перед обработкой ошибки с помощью оператора ?. Вы также должны использовать асинхронную среду выполнения, например tokio:

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
  let resp = reqwest::Client::new()
    .get("https://api.github.com/users/octocat")
    .send()
    .await?
    .json::<std::collections::HashMap<String, String>>()
    .await?;
  println!("{:#?}", resp);
  Ok(())
}

Обратите внимание, что для преобразования ответа в json, как показано выше, необходимо включить функцию json в вашем Cargo.toml:

reqwest = { version = "0.10.8", features = ["json"] }

Если вы не хотите использовать асинхронную среду выполнения, вы можете включить блокирующий reqwest клиент:

[dependencies]
reqwest = { version = "0.10", features = ["blocking", "json"] }

И используйте это так:

fn main() -> Result<(), Box<dyn std::error::Error>> {
  let resp = reqwest::blocking::Client::new()
    .get("https://api.github.com/users/octocat")
    .send()?
    .json::<std::collections::HashMap<String, String>>()?;
  println!("{:#?}", resp);
  Ok(())
}

Для API Github требуется еще пара параметров конфигурации. Вот минимальный рабочий пример с reqwest и github api:

use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
use serde::{Deserialize};

fn main() -> Result<(), Box<dyn std::error::Error>> {
  let mut headers = HeaderMap::new();
  // add the user-agent header required by github
  headers.insert(USER_AGENT, HeaderValue::from_static("reqwest"));

  let resp = reqwest::blocking::Client::new()
    .get("https://api.github.com/users/octocat")
    .headers(headers)
    .send()?
    .json::<GithubUser>()?;
  println!("{:#?}", resp);
  Ok(())
}

// Note that there are many other fields
// that are not included for this example
#[derive(Deserialize, Debug)]
pub struct GithubUser {
  login: String,
  id: usize,
  url: String,
  r#type: String,
  name: String,
  followers: usize
}
person Ibraheem Ahmed    schedule 03.11.2020
comment
Я получаю предупреждение и сообщение об ошибке: предупреждение: ящик Desktop должен иметь имя ящика змеи | = примечание: #[warn(non_snake_case)] по умолчанию включено = help: преобразовать идентификатор в случай змеи: desktop Ошибка: reqwest :: Error {вид: Декодировать, источник: Ошибка (ожидаемое значение, строка: 2, столбец: 1)} И он компилируется! Но у меня нет своего json ... Я пробовал использовать # [warn (non_snake_case)] Но ничего не изменилось - person Wolodia ZDETOVETZKY; 03.11.2020
comment
И я добавляю use std :: collections :: HashMap; в вашем коде, чтобы работать - person Wolodia ZDETOVETZKY; 03.11.2020
comment
Ошибка, которую вы получаете Error(expected value), не имеет ничего общего с reqwest. Преобразуйте запрос с .text() вместо .json() в ошибку, возвращаемую api github: Request forbidden by administrative rules. - person Ibraheem Ahmed; 03.11.2020
comment
@WolodiaZDETOVETZKY Я добавил к своему ответу минимальный пример. - person Ibraheem Ahmed; 03.11.2020