Reputation: 23
The data I'm trying to map to my struct comes in two formats:
With card_faces
, when there is more than one face to the card:
{
"object": "card",
"id": "some_id",
"lang": "en",
"released_at": "2012-02-03",
"card_faces": [
{
"name": "some_name",
"cost": "5",
"ctype": "some_type",
"colors": [
"R",
"B"
]
},
{
"name": "another_name",
"cost": "",
"ctype": "another_type",
"colors": [
"R",
"B"
]
}
],
"set_code": "some_code"
}
And without card_faces
, when there is only one face (the face fields are just placed in the root):
{
"object": "card",
"id": "some_id",
"lang": "en",
"released_at": "2012-02-03",
"name": "some_name",
"cost": "5",
"ctype": "some_type",
"colors": [
"R",
"B"
],
"set_code": "some_code"
}
I would like my struct to always have a Vec<CardFace>
field. Something like:
#[derive(Deserialize)]
struct Card {
object: String,
id: String,
lang: String,
released_at: String,
faces: Vec<CardFace>,
set_code: String,
}
Is it possible to deserialize these objects and coerce the face fields into the desired format or would I need to manipulate the json prior to deserializing?
Upvotes: 2
Views: 496
Reputation: 30001
I would do this using an intermediary enum
:
#[derive(Deserialize)]
#[serde(untagged)]
enum CardTmpDeser {
Card {
object: String,
id: String,
lang: String,
released_at: String,
card_faces: Vec<CardFace>,
set_code: String,
},
SingleCard {
object: String,
id: String,
lang: String,
released_at: String,
name: String,
cost: String,
ctype: String,
colors: Vec<String>,
set_code: String,
},
}
With the #[serde(untagged)]
attribute, you can transparently deserialize both kinds of data you have.
Now simply tag your actual structure with #[serde(from = "CardTmpDeser")]
:
#[derive(Debug, Deserialize)]
#[serde(from = "CardTmpDeser")]
pub struct Card {
object: String,
id: String,
lang: String,
released_at: String,
card_faces: Vec<CardFace>,
set_code: String,
}
and implement From<CardTmpDeser>
for Card
and you're good to go! serde
will automatically deserialize your data using CardTmpDeser
but will transparently convert it to your final type.
(Permalink to the playground with full working example)
Upvotes: 4