I am attempting to scrape the JSON from this endpoint https://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?;
}
I've tried two versions of the datastructure. Data is using a vector of latest, but i noticed each object has a unique ID, so in DataV2 i tried using a hashmap but i get the same error. I've also tried unnested versions without using Serde_with.
I get the error Error: reqwest::Error { kind: Decode, source: Error("invalid type: map, expected valid json object", line: 1, column: 8)
It seems my datastructure is messed up, but have been trying for hours to figure out the correct data structure to use.
CodePudding user response:
There are multiple issues with your current code.
Datav2
is closer, but still not correct. It is not aHashMap<u32, Vec<Latest>>
but aHashMap<u32, Latest>
. There is no need to have anotherVec
, since each number is assigned a value in the JSON.highTime
,low
,lowTime
are not of typeString
(since they have no quotes in the JSON), but are unsigned numbers (to be on the safe side I just assumed them to beu64
).- Apparently the fields of
Latest
can benull
, so they need to beOption
s. - I would still use snake_case for the field names in the
struct
s and then rename them to camelCase using the serde macro
I modified your code like I would do this, in order to give you an example of how it could be done:
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(())
}