Rust gql_client查询GraphQL端点报metric前语法错误
问题原因
报错本质是GraphQL查询语句语法不符合规范,同时存在后续反序列化类型不匹配的隐患:
- 字段参数位置错误:GraphQL中
query/mutation关键字后紧跟的操作名括号内,仅支持定义$变量名: 类型格式的查询变量,不能直接传入字段参数字面量。你将getMetric字段的metric: "dev_activity"参数错放到了操作声明位置,解析器读到非变量格式的metric字段直接抛出语法错误。 - 查询结构错位:
timeseriesData是getMetric字段下的子字段,你没有将其嵌套在getMetric的选择集(花括号范围)内,层级关系完全错误。 - 类型定义不匹配:接口返回的
value字段是浮点数格式(如1281.0),你在Rust结构体中定义为i64整数类型,即使查询语法修复,后续反序列化也会失败。 - 冗余声明:Rust 2021 edition不需要手动写
extern crate serde_derive;声明,该语句可直接删除。
修复方案
1. 修正GraphQL查询语句
将字段参数放回对应字段后,补全正确的嵌套结构:
let query = r#" query { getMetric(metric: "dev_activity") { timeseriesData( slug: "ethereum" from: "2020-02-10T07:00:00Z" to: "2020-03-10T07:00:00Z" interval: "1w" ) { datetime value } } } "#;
2. 修正结构体字段类型
将TimeseriesDatum的value字段类型从i64改为f64,匹配接口返回格式:
#[derive(Debug, Serialize, Deserialize)] pub struct TimeseriesDatum { pub datetime: String, pub value: f64, }
3. 优化错误处理
替换连续unwrap()逻辑,避免无意义panic:
let response = client.query::<DevActivity>(query).await? .ok_or("接口返回空响应")?;
修复后完整代码
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: f64, } #[tokio::main] async fn main() -> Result<(), Box<dyn std::error::Error>> { let query = r#" query { 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? .ok_or("接口返回空内容")?; for data in &response.data.get_metric.timeseries_data { println!("datetime {}, value {}", data.datetime, data.value) } Ok(()) }
后续排查方向
如果修复后仍有问题,按以下顺序检查:
- 先将写好的GraphQL语句放到对应服务的调试 playground 中验证,确认语句本身可以正常返回数据再放入代码
- 检查本地网络是否能正常访问目标API端点,无拦截、超时问题
- 核对serde的
rename配置与接口返回字段名完全一致,注意大小写敏感 - 确认依赖版本无兼容性问题,当前使用的
gql_client 1.0.4版本兼容上述写法
内容的提问来源于stack exchange,提问作者0xsegfault
相关产品推荐
相关产品推荐

