I am trying to take some json that looks like this:
{
"foo": "bar",
"name": "some name"
}
and use serde
to deserialize it to a data structure like this:
#[derive(Clone, PartialEq, Debug)]
pub struct Quux {
foo: Foo,
name: String,
}
pub enum Foo {
Bar,
Baz,
}
I have some code, but to be honest, it is pretty much straight out of the serde
guide to "deserializing without macros," and I'm not sure exactly what I would need to do to get it to deserialize the foo
field to a Foo
.
I have implemented Deserialize
for the Foo
enum, which I thought would be enough for the visitor.visit_value()
call in my impl serde::de::Vistor for QuuxVisitor
to call that version of deserialize
, but does not seem to be the case.
The error I get when I try to deserialize to Quux
is called 'Result::unwrap()' on an 'Err' value: SyntaxError("expected value", 2, 20)
, but if I change Quux
to use a String
for foo
instead of a Foo
, it deserializes fine.
There is a full example for Rust 1.18 / serde 1.0.0:
impl<'de> Deserialize<'de> for EventKind {
fn deserialize<D>(deserializer: D) -> result::Result<EventKind, D::Error>
where D: Deserializer<'de>
{
struct FieldVisitor {
min: usize,
};
impl<'de> Visitor<'de> for FieldVisitor {
type Value = EventKind;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a string containing at least {} bytes", self.min)
}
fn visit_str<E>(self, value: &str) -> result::Result<EventKind, E>
where E: serde::de::Error
{
let kind = match value {
"request" => EventKind::Request,
"ready" => EventKind::Ready,
"next" => EventKind::Next,
"reject" => EventKind::Reject,
"fail" => EventKind::Fail,
"done" => EventKind::Done,
"cancel" => EventKind::Cancel,
"suspended" => EventKind::Suspended,
s => {
return Err(serde::de::Error::invalid_value(serde::de::Unexpected::Str(s),
&self));
}
};
Ok(kind)
}
}
deserializer.deserialize_str(FieldVisitor { min: 4 })
}
}
enum EventKind {
Request,
Ready,
Next,
Reject,
Fail,
Done,
Cancel,
Suspended,
}
impl Serialize for EventKind {
fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
where S: Serializer
{
let kind = match *self {
EventKind::Request => "request",
EventKind::Ready => "ready",
EventKind::Next => "next",
EventKind::Reject => "reject",
EventKind::Fail => "fail",
EventKind::Done => "done",
EventKind::Cancel => "cancel",
EventKind::Suspended => "suspended",
};
serializer.serialize_str(kind)
}
}
You can see a similar example here.
Here is an example. I'm not sure about the best way to handle unknown fields, but this works:
extern crate serde;
use serde::de::{Deserialize, Deserializer, Visitor, Error};
pub enum Foo {
Bar,
Baz,
}
impl Deserialize for Foo {
fn deserialize<D>(deserializer: &mut D) -> Result<Foo, D::Error>
where D: Deserializer
{
struct FieldVisitor;
impl Visitor for FieldVisitor {
type Value = Foo;
fn visit_str<E>(&mut self, value: &str) -> Result<Foo, E>
where E: Error
{
match value {
"bar" => Ok(Foo::Bar),
"baz" => Ok(Foo::Baz),
_ => Err(E::syntax(&format!("Unexpected field: {}", value))),
}
}
}
deserializer.visit(FieldVisitor)
}
}
I used Rust 1.6.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With