我怎样才能从 Github API 得到 JSON?

How can I get JSON from the Github API?

我只想从下面的URL中得到一个JSON。

所以我使用了这段代码:

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; 但效果并不好。

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,您必须在 Cargo.toml:

中启用 json 功能
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(())
}

Github 的 api 需要几个其他配置选项。这是 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,
  #[serde(rename = "type")]
  ty: String,
  name: String,
  followers: usize
}