0

I have json from a vendor api that looks like this:

[
    "Crappy vendor unwanted string",
    [
        {
            "key": "val",
            "...": "lots more",
        },
        {
            "it": "goes on",
        }
    ]
]

I'm at a loss as to what to do here. Simply passing this as a vec to serde ala How to Deserialize a top level array doesn't work, as I don't know how to reference/pass the inner string and array to other structs.

I can simply do this:

    let json_string: String = res.text().await?;

however, that json string is unwieldy and unformatted. Not ideal.

Taking it a step further, I've created the following, which gets me close, but doesn't seem to work:

#[derive(Deserialize)]
pub struct Outer {
   pub outer_tite: String,
   pub inner_vec: Vec<Inner>,
}

#[derive(Deserialize)]
pub struct Inner {
    pub inner_obj: InnerObj,
}

#[derive(Deserialize)]
pub struct InnerObj {
    pub key1: String,
    pub key2: String,
    ...
}

impl Outer {
    pub async fn get(...) -> Result<Vec<Outer>, ExitFailure> {
        let out: Vec<Outer> = rec.json::<Vec<Outer>>().await?;
        ok(out)
    }
}

The result here is that the first string encountered throws an error:

value: error decoding response body: invalid type: string "Bad vendor string", expected struct Outer at line 2...

Changing the input json is not an option, as it's a vendor endpoint.

I've tried the suggestions from [How can I deserialize JSON with a top-level array using Serde?](How can I deserialize JSON with a top-level array using Serde?) - this does not work for my use case.

Herohtar
  • 5,347
  • 4
  • 31
  • 41

1 Answers1

0

You can directly deserialize a struct from a list of elements. The struct fields are deserialized in order. Your example code does not work since you only have one Outer element, containing multiple InnerObj. The Inner struct you added does not match the JSON structure you have shown.

The snippet shows how you can directly deserialize into the Outer struct, which contains the String and the Vec.

use serde::Deserialize;

#[derive(Deserialize)]
pub struct Outer {
   pub outer_titel: String,
   pub inner_vec: Vec<Inner>,
}

#[derive(Deserialize)]
pub struct Inner {
    pub key1: String,
    pub key2: String,
}

#[test]
fn deser() {
    let j = r#"[
    "Crappy vendor unwanted string",
    [
        {
            "key1": "val1",
            "key2": "val2"
        },
        {
            "key1": "val1",
            "key2": "val2"
        }
    ]
]"#;
    let outer: Outer = serde_json::from_str(j).unwrap();
    assert_eq!("Crappy vendor unwanted string", outer.outer_titel);
    assert_eq!(2, outer.inner_vec.len());
}

Playground

jonasbb
  • 2,131
  • 1
  • 6
  • 25