3

我正在尝试采用一些看起来像这样的 json:

{
    "foo": "bar",
    "name": "some name"
}

并用于serde将其反序列化为如下数据结构:

#[derive(Clone, PartialEq, Debug)]
pub struct Quux {
    foo: Foo,
    name: String,

}

pub enum Foo {
    Bar,
    Baz,
}

有一些代码,但老实说,它几乎直接来自serde“没有宏的反序列化”指南,我不确定我需要做什么才能将foo字段反序列化为Foo.

我已经DeserializeFoo枚举实现了,我认为这足以让visitor.visit_value()impl serde::de::Vistor for QuuxVisitor调用那个版本的deserialize,但似乎并非如此。

当我尝试反序列化时得到的错误Quuxcalled 'Result::unwrap()' on an 'Err' value: SyntaxError("expected value", 2, 20),但如果我Quux改为使用 a Stringforfoo而不是 a Foo,它反序列化很好。

4

3 回答 3

3

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)
    }
}

你可以在这里看到一个类似的例子。

于 2017-04-14T18:28:23.597 回答
2

这是一个例子。我不确定处理未知字段的最佳方法,但这有效:

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)
    }
}

我使用了 Rust 1.6。

于 2016-02-01T20:04:52.237 回答
2

我建议使用serde_derive来生成Deserialize实现,而不是手动写出来。

在下面的代码中,我使用 a#[serde(rename_all = "lowercase")]Foo接受 JSON 表示"bar""baz"而不是默认值"Bar",并"Baz"对应于 Rust 代码中的大小写。

#[macro_use]
extern crate serde_derive;
extern crate serde;

#[derive(Deserialize, Debug)]
struct Quux {
    foo: Foo,
    name: String,
}

#[derive(Deserialize, Debug)]
#[serde(rename_all = "lowercase")]
enum Foo {
    Bar,
    Baz,
}

fn main() {
    let j = r#"
        {
            "foo": "bar",
            "name": "some name"
        }
        "#;

    println!("{:#?}", serde_json::from_str::<Quux>(j).unwrap());
}
于 2018-11-12T21:48:58.720 回答