Serde has me stumped. Request error with json

I'm trying to pull this info into a struct and cant seem to get it to compile.

use serde::{Serialize, Deserialize};





#[derive(Debug, Serialize, Deserialize)]
struct KujiraAssetInfo {
    base_currency: String,
    ask: f64,
    base_volume: f64,
    bid: f64,
    high: f64,
    last_price: f64,
    low: f64,
    pool_id: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resp = reqwest::get("https://api.kujira.app/api/coingecko/tickers").await?;
       

    let resp_json = resp.json::<Vec<KujiraAssetInfo>>()
        .await?;

        println!("Responce Json: {:#?}", resp_json);
        Ok(())

    
}

When i run the code i get this error message.
Error: reqwest::Error { kind: Decode, source: Error("invalid type: map, expected a sequence", line: 1, column: 0) }

Any help or ideas is greatly appreciated

It means the top level structure of the response JSON is the JSON object, not the JSON array. The Vec expects JSON array. For the debugging you can use .text() instead of the .json() to view the raw response text.

3 Likes

thanks for the advice. How can i get the top level response to be a JSON array?

Are you in control of Kujira server? If no, there is no way to get the response to be a JSON array. You are using Kujira API, so you should work with what you are given.

1 Like

Ok is there a way to disregard the top level Structure which i believe is just "tickers" so that i can use the rest of the data as a Vec in the struct?

Just create a wrapper struct that matches the format of the JSON you're receiving

1 Like

Can you explain what you mean like I'm 5

If your JSON looks like

{
    "assets": [{
        "base_currency": ... 
    }]
}

Create a struct

#[derive(Debug, Serialize, Deserialize)]
struct KujiraAssets {
    assets: Vec<KujiraAssetInfo>,
}

And deserialize that instead. Obviously you'll have to rename the field to match whatever is in the JSON

1 Like

So i added

use serde::{Serialize, Deserialize};


#[derive(Debug, Serialize, Deserialize)]
struct Obj {
    tickers: Vec<Tickers>,
}

#[derive(Debug, Serialize, Deserialize)]
struct Tickers {
    ask: f64,
    base_currency: String,
    base_volume: f64,
    bid: f64,
    high: f64,
    last_price: f64,
    low: f64,
    pool_id: String,
    target_currency: String,
    target_volume: String,
    ticker_id: String,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let resp = reqwest::get("https://api.kujira.app/api/coingecko/tickers").await?;



    let resp_json = resp.json::<Vec<Tickers>>()
        .await?;

        println!("Responce Json: {:#?}", resp_json);
        Ok(())

    
}

and I'm still getting the same error message? I know I must be missing something obvious

Looks like you're not deserializing the new type

3 Likes

the new type is the New Struct wrapper correct? how do i deserialize the new type?

You specify it instead of the Vec<_> in the type annotation. But for basic stuff like this, you should really read Serde's documentation.

2 Likes

Try resp.json::<Obj>() instead of resp.json::<Vec<Tickers>>().

1 Like

thanks for your response. i understand now. What i had to do was replace <vec> with . I was using () initially so.