如何使用动态字段名称反序列化响应?
How to deserialize response with dynamic field name?
正在尝试反序列化 rust get 请求的响应。以下请求似乎工作正常。但是,我想知道是否有一个很好的方法来模拟 TradeResult
。现在它有 XXBTZUSD 硬编码。我希望这是任何类型的一对。尝试在 Trades
结果上使用 HashMap<String, TradeResultTypes>
类型;希望这将允许最后一个 属性 和正在检索的那对,但似乎无法让它工作,除非这对像下面那样被硬编码。
extern crate serde;
#[macro_use]
extern crate serde_derive;
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp: Trades = reqwest::blocking::get("https://api.kraken.com/0/public/Trades?pair=XBTUSD")?.json()?;
println!("{:?}", resp);
Ok(())
}
#[derive(Debug, Deserialize)]
struct Trades {
result: TradeResult,
error: Vec<u32>,
}
// #[derive(Debug, Deserialize)]
// struct Trades {
// result: HashMap<String, TradeResultTypes>,
// error: Vec<u32>,
// }
#[derive(Debug, Deserialize)]
struct TradeResult {
last: String,
XXBTZUSD: TradeData,
}
// (price, volume, time, side, orderType, misc)`
type TradeData = Vec<(String, String, f64, String, String, String)>;
#[derive(Debug, Deserialize)]
enum TradeResultTypes {
String,
TradeData,
}
您可以使用 untagged
属性反序列化 String
或 TradeData
:
#[derive(Debug, Deserialize)]
struct Trades {
result: HashMap<String, TradeResultTypes>,
error: Vec<u32>,
}
// (price, volume, time, side, orderType, misc)`
type TradeData = Vec<(String, String, f64, String, String, String)>;
#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum TradeResultTypes {
String (String),
TradeData (TradeData),
}
这样,serde 将首先尝试反序列化 String
。如果有效,它将 return 一个 TradeResultTypes::String
。如果它不起作用,它将尝试反序列化一个元组数组。如果可行,它将 return 一个 TradeResultTypes::TradeData
,否则它将 return 一个错误。
请注意,您需要告诉 Rust 要存储在 enum
的每个变体中的值的类型。换句话说,当我在 enum
中写 String (String)
时,第一个 String
只是一个标签(由于 untagged
属性,serde 将忽略它),第二个 String
是它应该包含的数据类型。它也适用于:
#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum TradeResultTypes {
Last (String),
Quotations (TradeData),
}
正在尝试反序列化 rust get 请求的响应。以下请求似乎工作正常。但是,我想知道是否有一个很好的方法来模拟 TradeResult
。现在它有 XXBTZUSD 硬编码。我希望这是任何类型的一对。尝试在 Trades
结果上使用 HashMap<String, TradeResultTypes>
类型;希望这将允许最后一个 属性 和正在检索的那对,但似乎无法让它工作,除非这对像下面那样被硬编码。
extern crate serde;
#[macro_use]
extern crate serde_derive;
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let resp: Trades = reqwest::blocking::get("https://api.kraken.com/0/public/Trades?pair=XBTUSD")?.json()?;
println!("{:?}", resp);
Ok(())
}
#[derive(Debug, Deserialize)]
struct Trades {
result: TradeResult,
error: Vec<u32>,
}
// #[derive(Debug, Deserialize)]
// struct Trades {
// result: HashMap<String, TradeResultTypes>,
// error: Vec<u32>,
// }
#[derive(Debug, Deserialize)]
struct TradeResult {
last: String,
XXBTZUSD: TradeData,
}
// (price, volume, time, side, orderType, misc)`
type TradeData = Vec<(String, String, f64, String, String, String)>;
#[derive(Debug, Deserialize)]
enum TradeResultTypes {
String,
TradeData,
}
您可以使用 untagged
属性反序列化 String
或 TradeData
:
#[derive(Debug, Deserialize)]
struct Trades {
result: HashMap<String, TradeResultTypes>,
error: Vec<u32>,
}
// (price, volume, time, side, orderType, misc)`
type TradeData = Vec<(String, String, f64, String, String, String)>;
#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum TradeResultTypes {
String (String),
TradeData (TradeData),
}
这样,serde 将首先尝试反序列化 String
。如果有效,它将 return 一个 TradeResultTypes::String
。如果它不起作用,它将尝试反序列化一个元组数组。如果可行,它将 return 一个 TradeResultTypes::TradeData
,否则它将 return 一个错误。
请注意,您需要告诉 Rust 要存储在 enum
的每个变体中的值的类型。换句话说,当我在 enum
中写 String (String)
时,第一个 String
只是一个标签(由于 untagged
属性,serde 将忽略它),第二个 String
是它应该包含的数据类型。它也适用于:
#[derive(Debug, Deserialize)]
#[serde(untagged)]
enum TradeResultTypes {
Last (String),
Quotations (TradeData),
}