-
-
Notifications
You must be signed in to change notification settings - Fork 792
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conditionally deserialize sub-struct based on visited values #1470
Comments
I would write this as: impl<'de> Deserialize<'de> for ItemEvent {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize, Debug)]
enum EventType {
#[serde(rename = "item.created")]
Created,
#[serde(rename = "item.deleted")]
Deleted,
}
#[derive(Deserialize)]
struct EventHelper {
t: EventType,
v: u32,
data: serde_json::Value,
}
let helper = EventHelper::deserialize(deserializer)?;
match (helper.t, helper.v) {
(EventType::Created, 1) => Created::deserialize(helper.data)
.map(ItemEvent::Created)
.map_err(de::Error::custom),
(EventType::Deleted, 1) => Deleted::deserialize(helper.data)
.map(ItemEvent::Deleted)
.map_err(de::Error::custom),
(t, v) => Err(de::Error::custom(format!(
"unrecognized version v={} for event {:?}",
v, t
))),
}
}
} |
@dtolnay thanks, but that would work only for JSON as |
You could use serde_value::Value in place of serde_json::Value. |
@dtolnay I have somewhat of a similar use case, but for quite a big struct with a lot of aliases. So I was wondering if there is a way to do something like this, but without having to copy over the whole struct as a helper struct (as it's really pretty big)? Using the same struct inside the Thanks!! |
Maybe good to elaborate a little on how my use case could be similar. I have a struct with a value containing an enum of enums and which enum that should be used is dependent on another field. So my idea was (following the above approach) to deserialize the whole struct, but use a temp So something like this: #[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum Model {
Model1(Serie1),
Model2(Serie2),
}
#[derive(Serialize_repr, Deserialize_repr, Clone, Debug)]
#[allow(non_camel_case_types)]
#[repr(i8)]
pub enum Serie1 {
#[serde(rename(deserialize = "SubModel 1"))]
SubModel1 = 0,
#[serde(rename(deserialize = "SubModel 2"))]
SubModel2 = 1,
}
#[derive(Serialize_repr, Deserialize_repr, Clone, Debug)]
#[repr(i8)]
pub enum Serie2 {
#[serde(rename(deserialize = "Model 123"))]
Model1= 0,
#[serde(rename(deserialize = "Model 234"))]
Model2 = 1,
#[serde(rename(deserialize = "Model 345"))]
Model3 = 2,
}
struct SomeDevice {
driver: String,
model: Model,
} Of course this is very simplified, but I think the idea is clear. The issue is that there are multiple sub enums that represent Hope this solution can also be used for this use case, but of course any other pointers are more then welcome as well! Thanks! |
@dtolnay do you prefer that I open a new support issue for this instead? |
I need to deserialize the following list
into
Vec<ItemEvent>
whereItemEvent
is defined as the following:I've checked/tried the following things with no success:
t
/v
fields during deserialization theVisitor
should definitely be used.Visitor
implementation examples which I've found:visit_map()
just ends withOk(MyType{})
;MapAccess
received invisit_map()
.I've ended up with somewhat following
which does not actually compile.
The question is: how one could forward deserialization inside
visit_map()
, but only for one field, not the whole receivedMapAccess
?The text was updated successfully, but these errors were encountered: