我正试图从该端点抓取JSONhttps://prices.runescape.wiki/api/v1/osrs/latest。
#[derive(Serialize, Deserialize, Debug)]
struct Latest {
high: u32,
highTime: String,
low: String,
lowTime: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct Data {
#[serde(with = "serde_with::json::nested")]
data: Vec<Latest>,
}
#[derive(Serialize, Deserialize, Debug)]
struct Datav2 {
#[serde(with = "serde_with::json::nested")]
data: HashMap<u32, Vec<Latest>>,
}
#[cfg(not(target_arch = "wasm32"))]
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let res = reqwest::get(url).await?;
let response = &res.json::<Datav2>().await?;
}
我已经尝试了两个版本的数据结构。数据使用的是最新的向量,但我注意到每个对象都有一个唯一的ID,所以在DataV2中我尝试使用哈希映射,但我得到了同样的错误。我还尝试过不使用Serde_with的未测试版本。
我得到错误Error: reqwest::Error { kind: Decode, source: Error("invalid type: map, expected valid json object", line: 1, column: 8)
我的数据结构似乎一团糟,但我已经花了几个小时的时间试图找出要使用的正确数据结构。
当前代码存在多个问题。
Datav2
更接近,但仍然不正确。它不是HashMap<u32, Vec<Latest>>
,而是HashMap<u32, Latest>
。不需要有另一个Vec
,因为在JSON中为每个数字分配了一个值highTime
、low
、lowTime
不是String
类型(因为它们在JSON中没有引号),而是无符号数字(为了安全起见,我只是假设它们是u64
)- 显然,
Latest
的场可以是null
,所以它们需要是Option
s - 我仍然会对
struct
s中的字段名使用snake_case,然后使用serde宏将它们重命名为camelCase
我像这样修改了你的代码,以便给你一个如何完成的例子:
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "camelCase")]
struct Latest {
high: Option<u64>,
high_time: Option<u64>,
low: Option<u64>,
low_time: Option<u64>,
}
#[derive(Serialize, Deserialize, Debug)]
struct Data {
data: HashMap<u64, Latest>,
}
#[cfg(not(target_arch = "wasm32"))]
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let url = "https://prices.runescape.wiki/api/v1/osrs/latest";
let res = reqwest::get(url).await?;
let response = &res.json::<Data>().await?;
println!("{:#?}", response);
Ok(())
}