Wolodia ZDETOVETZKY
Wolodia ZDETOVETZKY

Reputation: 3

How can I get JSON from the Github API?

I just want to get a JSON from the following URL.

So I used this code:

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(())
}

But I don't know how to solve the error :

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`.

but I can also obtain what I want with a simple

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

I've tried to add use std::ops::Try; but it doesn't work better.

Upvotes: 0

Views: 1232

Answers (1)

Ibraheem Ahmed
Ibraheem Ahmed

Reputation: 13618

The reqwest crate uprovides an asynchronous api by default. Therefore you have to .await before handling the error with the ? operator. You also have to use an async runtime, such as 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(())
}

Note that to use convert the response to json as shown above, you must enable the json feature in your Cargo.toml:

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

If you don't want to use an async runtime, you can enable the blocking reqwest client:

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

And use it like so:

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's api requires a couple other config options. Here is a minimal working example with reqwest and the 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
}

Upvotes: 4

Related Questions