Module miniserde::de [−][src]
Deserialization traits.
Deserialization in miniserde works by returning a "place" into which data
may be written through the methods of the Visitor
trait object.
Use the make_place!
macro to acquire a "place" type. A library may use a
single place type across all of its Deserialize impls, or each impl or each
module may use a private place type. There is no difference.
A place is simply:
struct Place<T> { out: Option<T>, }
Upon successful deserialization the output object is written as Some(T)
into the out
field of the place.
Deserializing a primitive
The Visitor trait has a method corresponding to each supported primitive type.
#[macro_use] extern crate miniserde; use miniserde::Result; use miniserde::de::{Deserialize, Visitor}; make_place!(Place); struct MyBoolean(bool); // The Visitor trait has a selection of methods corresponding to different // data types. We override the ones that our Rust type supports // deserializing from, and write the result into the `out` field of our // output place. // // These methods may perform validation and decide to return an error. impl Visitor for Place<MyBoolean> { fn boolean(&mut self, b: bool) -> Result<()> { self.out = Some(MyBoolean(b)); Ok(()) } } impl Deserialize for MyBoolean { fn begin(out: &mut Option<Self>) -> &mut Visitor { // All Deserialize impls will look exactly like this. There is no // other correct implementation of Deserialize. Place::new(out) } }
Deserializing a sequence
In the case of a sequence (JSON array), the visitor method returns a builder that can hand out places to write sequence elements one element at a time.
#[macro_use] extern crate miniserde; use miniserde::Result; use miniserde::de::{Deserialize, Seq, Visitor}; use std::mem; make_place!(Place); struct MyVec<T>(Vec<T>); impl<T: Deserialize> Visitor for Place<MyVec<T>> { fn seq(&mut self) -> Result<Box<Seq + '_>> { Ok(Box::new(VecBuilder { out: &mut self.out, vec: Vec::new(), element: None, })) } } struct VecBuilder<'a, T: 'a> { // At the end, output will be written here. out: &'a mut Option<MyVec<T>>, // Previous elements are accumulated here. vec: Vec<T>, // Next element will be placed here. element: Option<T>, } impl<'a, T: Deserialize> Seq for VecBuilder<'a, T> { fn element(&mut self) -> Result<&mut Visitor> { // Free up the place by transfering the most recent element // into self.vec. self.vec.extend(self.element.take()); // Hand out a place to write the next element. Ok(Deserialize::begin(&mut self.element)) } fn finish(&mut self) -> Result<()> { // Transfer the last element. self.vec.extend(self.element.take()); // Move the output object into self.out. let vec = mem::replace(&mut self.vec, Vec::new()); *self.out = Some(MyVec(vec)); Ok(()) } } impl<T: Deserialize> Deserialize for MyVec<T> { fn begin(out: &mut Option<Self>) -> &mut Visitor { // As mentioned, all Deserialize impls will look like this. Place::new(out) } }
Deserializing a map or struct
This code demonstrates what is generated for structs by
#[derive(MiniDeserialize)]
.
#[macro_use] extern crate miniserde; use miniserde::Result; use miniserde::de::{Deserialize, Map, Visitor}; make_place!(Place); // The struct that we would like to deserialize. struct Demo { code: u32, message: String, } impl Visitor for Place<Demo> { fn map(&mut self) -> Result<Box<Map + '_>> { // Like for sequences, we produce a builder that can hand out places // to write one struct field at a time. Ok(Box::new(DemoBuilder { code: None, message: None, out: &mut self.out, })) } } struct DemoBuilder<'a> { code: Option<u32>, message: Option<String>, out: &'a mut Option<Demo>, } impl<'a> Map for DemoBuilder<'a> { fn key(&mut self, k: &str) -> Result<&mut Visitor> { // Figure out which field is being deserialized and return a place // to write it. // // The code here ignores unrecognized fields but an implementation // would be free to return an error instead. Similarly an // implementation may want to check for duplicate fields by // returning an error if the current field already has a value. match k { "code" => Ok(Deserialize::begin(&mut self.code)), "message" => Ok(Deserialize::begin(&mut self.message)), _ => Ok(Visitor::ignore()), } } fn finish(&mut self) -> Result<()> { // Make sure we have every field and then write the output object // into self.out. let code = self.code.take().ok_or(miniserde::Error)?; let message = self.message.take().ok_or(miniserde::Error)?; *self.out = Some(Demo { code, message }); Ok(()) } } impl Deserialize for Demo { fn begin(out: &mut Option<Self>) -> &mut Visitor { // All Deserialize impls look like this. Place::new(out) } }
Traits
Deserialize |
Trait for data structures that can be deserialized from a JSON string. |
Map |
Trait that can hand out places to write values of a map. |
Seq |
Trait that can hand out places to write sequence elements. |
Visitor |
Trait that can write data into an output place. |