Search code examples
rustgraphqlserde

Unable to parse graphql endpoint


I am trying to parse the response to a graphql endpoint using this code:

extern crate serde_derive;

use gql_client::Client;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct DevActivity {
    pub data: Data,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Data {
    #[serde(rename = "getMetric")]
    pub get_metric: GetMetric,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct GetMetric {
    #[serde(rename = "timeseriesData")]
    pub timeseries_data: Vec<TimeseriesDatum>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TimeseriesDatum {
    pub datetime: String,
    pub value: i64,
}

#[derive(Serialize)]
pub struct Vars {
    metric: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let query = r#"
    {
        getMetric(metric: "dev_activity") {
          timeseriesData(slug: "ethereum", from: "2020-02-10T07:00:00Z", to: "2020-03-10T07:00:00Z", interval: "1w") {
            datetime
            value
          }
        }
      }
        "#;

    let endpoint = "https://api.santiment.net/graphql";
    let client = Client::new(endpoint);
    let response = client.query::<DevActivity>(query).await.unwrap().unwrap();
    for data in &response.data.get_metric.timeseries_data {
        println!("datetime {}, value {}", data.datetime, data.value)
    }
    Ok(())
}

However I get the following error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: 
GQLClient Error: Failed to parse response: Error("missing field `data`", line: 1, column: 294). The response body is: {"data":{"getMetric":{"timeseriesData":[{"datetime":"2020-02-06T00:00:00Z","value":795.0},{"datetime":"2020-02-13T00:00:00Z","value":1281.0},{"datetime":"2020-02-20T00:00:00Z","value":1115.0},{"datetime":"2020-02-27T00:00:00Z","value":952.0},{"datetime":"2020-03-05T00:00:00Z","value":605.0}]}}}
', src/main.rs:49:61

I am unsure what the error is , as the struct I am pssing it to has a data field


Solution

  • The gql_client crate appears to parse the top-level structure (composing of data and/or errors) on your behalf. Probably because its part of the graphql spec and you shouldn't need to worry about it. So you don't need the DevActivity structure at all and simply use Data:

    let response = client.query::<Data>(query).await.unwrap().unwrap();
    for data in &response.get_metric.timeseries_data {
        ...
    }