Take for example this GoogleBooks API response
{
"kind": "books#volumes",
"totalItems": 10,
"items": [
{
"kind": "books#volume",
"id": "id",
"etag": "tag",
"selfLink": "link.to.somewhere",
"volumeInfo": {
"title": "some title",
"authors": [
"author 1",
"author 2"
],
"publisher": "some publisher",
"...": "..."
}
},
{
"...": "...",
"volumeInfo": {}
},
{
"...": "...",
"volumeInfo": {}
}
]
}
I am only interested in values of "volumeInfo"
key but because it's nested inside "items"
, I need to deserialize outer levels to get to it.
Fortunately serde
makes it very easy:
#[derive(Debug, Deserialize)]
struct Items {
items: Vec<VolumeInfo>,
}
#[derive(Debug, Deserialize)]
struct VolumeInfo {
#[serde(rename = "volumeInfo", deserialize_with = "deserialize")]
volume_info: Book,
}
But problem get compounded if there's a key that depends on the arguments you provided for the call, for example this OpenLibrary API response
{
"ISBN:SomeISBN": {
"url": "link.to.somewhere",
"key": "...",
"title": "...",
"subtitle": "...",
"authors": [ "..." ],
...
}
}
Here the key "ISBN:SomeISBN"
depends on the the call args so I am having to first deserialize this response into just serde_json::Value
let mut response: serde_json::Value = reqwest::get(req)...?;
and then index into response and parse it again
struct ISBNResponse(#[serde(deserialize_with = "deserialize")] Book);
let ISBNResponse(book) = serde_json::from_value(response[isbn_key].take())...?
I am not sure if parsing into serde_json::Value
and parsing again is more expensive than parsing into a struct like I did for Google Books but either way I think parsing the relevant inner struct directly could be faster than either.
Looking around I found
#[serde(flatten)]
and
#[serde(tag = "...", content = "...")]
but I don't think that's exactly what I am looking for.