在rust中反序列化API中的serde_json



我正试图从该端点抓取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)

我的数据结构似乎一团糟,但我已经花了几个小时的时间试图找出要使用的正确数据结构。

当前代码存在多个问题。

  1. Datav2更接近,但仍然不正确。它不是HashMap<u32, Vec<Latest>>,而是HashMap<u32, Latest>。不需要有另一个Vec,因为在JSON中为每个数字分配了一个值
  2. highTimelowlowTime不是String类型(因为它们在JSON中没有引号),而是无符号数字(为了安全起见,我只是假设它们是u64)
  3. 显然,Latest的场可以是null,所以它们需要是Options
  4. 我仍然会对structs中的字段名使用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(())
}

最新更新