Rust中serde_json反序列化Binance API响应报错求助
Binance API 24小时行情反序列化错误解决
问题详情
调用Binance的/api/v1/ticker/24hr接口获取JSON数据,使用serde_json反序列化时触发错误:
Error("invalid type: map, expected a sequence", line: 1, column: 1)
接口返回的JSON结构(格式化后)
{ "symbol": "ETHBTC", "priceChange": "0.00068700", "priceChangePercent": "0.874", "weightedAvgPrice": "0.07908580", "prevClosePrice": "0.07864600", "lastPrice": "0.07933400", "lastQty": "0.18460000", "bidPrice": "0.07933400", "bidQty": "4.49640000", "askPrice": "0.07933500", "askQty": "54.13430000", "openPrice": "0.07864700", "highPrice": "0.07945000", "lowPrice": "0.07846100", "volume": "56892.20330000", "quoteVolume": "4499.36548634", "openTime": 1662288072375, "closeTime": 1662374472375, "firstId": 369847410, "lastId": 370015037, "count": 167628 }
原代码
use serde::Deserialize; use std::error::Error; #[derive(Deserialize, Debug)] struct Peers { num: Vec<Peer>, } #[derive(Deserialize, Debug)] struct Peer { symbol: String, count: u32, } fn get_node(url: &str) -> Result<Peer, Box<dyn Error>> { let response = ureq::get(url).call()?.into_string()?; let node: Peers = serde_json::from_str(&response)?; dbg!(node); todo!() } fn main() { let url = "https://api.binance.com/api/v1/ticker/24hr"; let num = get_node(url); dbg!(num); todo!() }
终端报错信息
num = Err( Error("invalid type: map, expected a sequence", line: 1, column: 1), ) thread 'main' panicked at 'not yet implemented', note: run with `RUST_BACKTRACE=1` environment variable to display a
错误原因
- 原代码定义的
Peers结构体期望JSON是包含num数组的对象(格式如{"num": [{}, {}]}),但Binance该接口实际返回的是单个交易对对象(不带symbol参数时返回所有交易对的数组),结构完全不匹配。 - 函数返回值定义为
Result<Peer, ...>,但代码中反序列化的是Peers类型,类型不兼容。
修正方案
根据接口调用场景选择对应修正方式:
场景1:获取单个交易对的24小时行情
若接口URL指定了symbol参数(比如https://api.binance.com/api/v1/ticker/24hr?symbol=ETHBTC),直接将JSON反序列化为Peer结构体:
use serde::Deserialize; use std::error::Error; #[derive(Deserialize, Debug)] struct Peer { symbol: String, count: u32, // 需使用其他字段时,在此添加对应定义 } fn get_node(url: &str) -> Result<Peer, Box<dyn Error>> { let response = ureq::get(url).call()?.into_string()?; let node: Peer = serde_json::from_str(&response)?; dbg!(node); Ok(node) } fn main() { let url = "https://api.binance.com/api/v1/ticker/24hr?symbol=ETHBTC"; let result = get_node(url); dbg!(result); }
场景2:获取所有交易对的24小时行情
若调用不带symbol参数的接口,返回的是交易对象数组,需反序列化为Vec<Peer>:
use serde::Deserialize; use std::error::Error; #[derive(Deserialize, Debug)] struct Peer { symbol: String, count: u32, // 需使用其他字段时,在此添加对应定义 } fn get_nodes(url: &str) -> Result<Vec<Peer>, Box<dyn Error>> { let response = ureq::get(url).call()?.into_string()?; let nodes: Vec<Peer> = serde_json::from_str(&response)?; dbg!(nodes); Ok(nodes) } fn main() { let url = "https://api.binance.com/api/v1/ticker/24hr"; let result = get_nodes(url); dbg!(result); }
注意事项
- 若需使用接口返回的其他字段,需在
Peer结构体中添加对应字段定义,字段名需与JSON键完全一致(或通过#[serde(rename = "xxx")]重命名)。 - 确保依赖已正确添加到
Cargo.toml:
[dependencies] serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" ureq = "2.6"
内容的提问来源于stack exchange,提问作者Arunjot Singh
相关产品推荐
相关产品推荐

