rustwigle

Rust JSON API Request Formatting


I am trying to perform a search request given the API structure by: https://api.wigle.net/swagger#/

Currently, I have attempted to perform a /api/v2/network/search through the given structure by doing this (sorry for the long url!):

#[macro_use]
extern crate serde;
extern crate serde_derive;
extern crate reqwest;
use reqwest::Error;
use serde_json;

#[derive(Deserialize, Debug)]
struct Output {
    trilat: f64,
    trilong: f64,
}

fn main() -> Result<(), Error> {
    let request_url = format!("https://api.wigle.net/api/v2/network/search?first=0&latrange1={lat_range_min}&latrange2={lat_range_max}&longrange1={long_range_min}&longrange2={long_range_max}&freenet=false&paynet=false&ssid={ssid}",
                              lat_range_min = "41.159",
                              lat_range_max = "42.889",
                              long_range_min = "-73.5081",
                              long_range_max = "-69.7398",
                              ssid= "XFINITY"
                            );

    let mut response = reqwest::get(&request_url)?;

    println!("{:?}", response);

    //let result: Vec<Output> = response.json()?;
    //println!("{}", result[0].trilat);
    Ok(())
}

The output I get is:

Response { url: "https://api.wigle.net/api/v2/network/search?first=0&latrange1=41.159&latrange2=42.889&longrange1=-73.5081&longrange2=-69.7398&freenet=false&paynet=false&ssid=xfinity", status: 401, headers: 
{"server": "nginx/1.16.1", "date": "Tue, 24 Dec 2019 19:51:14 GMT", "content-type": "application/json", "content-length": "14", "connection": "keep-alive"} }

However if you were to do an actual request, you would get detailed api output from WiGLE.

What do I do in order to get the correct output so I can parse it as a json output?

Thanks!


Solution

  • This crate doesn't support such a possibility to transform its type Response to the serde_json::Value type. But you can implement it by yourself.

    You should define your structure and operate on it. For instanse it may be somehow like the following:

    use serde::{Serialize, Deserialize};
    use std::collections::HashMap;
    use serde_json;
    use reqwest;
    use reqwest::Error;
    
    #[derive(Serialize, Deserialize, Debug)]
    struct Req {
      url: String,
      status: u16,
      headers: HashMap<String, String>,
      body: Option<serde_json::Value>
    }
    
    fn main() -> Result<(), Error> {
        let request_url = format!("https://api.wigle.net/api/v2/network/search?first=0&latrange1={lat_range_min}&latrange2={lat_range_max}&longrange1={long_range_min}&longrange2={long_range_max}&freenet=false&paynet=false&ssid={ssid}",
                                  lat_range_min = "41.159",
                                  lat_range_max = "42.889",
                                  long_range_min = "-73.5081",
                                  long_range_max = "-69.7398",
                                  ssid= "xfinity"
                                );
        let mut response = reqwest::get(&request_url)?;
        let mut hm = HashMap::new();
        for (key, val) in response.headers().into_iter() {
          hm.insert(key.as_str().to_owned(), val.to_str().ok().unwrap_or("").to_owned());
        }
    
        let req = Req {status: response.status().as_u16(), url: request_url, body: response.json().ok(), headers: hm};
    
        println!("{}", serde_json::to_string(&req).unwrap_or("".to_owned()));
    
    
        Ok(())
    }
    

    to improve such a solution you can implement the trait From not to be so descriptive each time.