sezna
February 5, 2022, 5:26am
1
Hello! I've tried searching around for help on this, but I'm not finding any resources.
I have an enum that looks something like this:
enum Foo {
VariantOne {
field_one: u64,
field_two: u64,
},
VariantTwo {
field_one: String,
},
VariantThree,
}
Each enum variant has different data. I'd like to be able to deserialize this in a custom way. For example, if I have a csv:
variant_name, field_one, field_two
variant_one, 1, 1
variant_three
variant_two, 100
I'd like to be able to handle this with serde
and Deserialize
.
I've tried reading the documentation on the Visitor pattern, but it isn't clear to me. Should I be visiting a sequence and handling each part individually?
Yes, that would be a valid solution. And also a good one for the problem you have.
1 Like
sezna
February 5, 2022, 6:39am
3
I ended up sorting it out. For anybody who comes across this:
impl<'de> Deserialize<'de> for Foo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct FooVisitor;
impl<'de> Visitor<'de> for FooVisitor {
type Value = Foo;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("enum Foo")
}
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
where
V: SeqAccess<'de>,
{
let foo_type = FooType::from_str(
seq.next_element()?
.ok_or_else(|| de::Error::invalid_length(0, &self))?,
);
match FooType {
FooType::VariantOne => {
let field_one: u64 = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
let field_two: u64 = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(2, &self))?;
return Ok(Foo::VariantOne { field_one, field_two })
},
FooType::VariantTwo => ...etc., omitted for brevity,
}
}
}
deserializer.deserialize_seq(TransactionVisitor)
}
}
enum FooType {
VariantOne,
VariantTwo,
VariantThree
}
impl FooType {
fn from_str(raw: &str) -> Self {
match raw {
"variant_one" => FooType::VariantOne,
... etc., omitted for brevity
}
}
system
Closed
May 6, 2022, 6:39am
4
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.