2016-02-01 2 views
2

Я пытаюсь принять некоторые JSON, который выглядит следующим образом:Deserialize на структуру с членом перечислений

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

и использовать serde десериализации его в структуру данных, как это:

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

} 

pub enum Foo { 
    Bar, 
    Baz, 
} 

I have some code, но, честно говоря, это довольно прямолинейно из руководства serde «десериализация без макросов», и я не уверен, что мне нужно будет сделать, чтобы десериализовать поле foo на Foo.

Я реализовал Deserialize для Foo перечисления, который я думал, было бы достаточно для visitor.visit_value() вызова в моем impl serde::de::Vistor for QuuxVisitor позвонить эту версию deserialize, но, кажется, не так.

Я получаю ошибку, когда я пытаюсь десериализации к Quux является called 'Result::unwrap()' on an 'Err' value: SyntaxError("expected value", 2, 20), но если я изменю Quux использовать String для foo вместо Foo, это десериализует хорошо.

ответ

1

Вот пример. Я не уверен в лучшем способе обработки неизвестных полей, но это работает:

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.

+1

Да, это приведет к десериализации перечисления, но когда структура имеет член, который имеет тип 'enum Foo', десериализация структуры не использует' Deserialize' impl для 'Foo'. –

1

Существует полный пример 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) 
    } 
} 

Вы можете увидеть аналогичный пример here.

Смежные вопросы