I want to have the Test::team_size
attribute be deserialized from the data of Test
object itself:
#[derive(Debug, Serialize, Deseri
The Serde documentation has a chapter on how to implement custom deserialization when the autogenerated attributes don't fully do what you want. Starting from there, it's not too complicated, just tedious:
extern crate serde;
extern crate serde_json;
use std::fmt;
use serde::de::{self, Deserialize, Deserializer, Visitor, MapAccess};
#[derive(Debug)]
struct TeamSize {
pub min: i64,
pub max: i64,
}
#[derive(Debug)]
struct Test {
pub i: i64,
pub team_size: TeamSize,
}
impl<'de> Deserialize<'de> for Test {
fn deserialize(deserializer: D) -> Result
where D: Deserializer<'de>
{
struct TestVisitor;
impl<'de> Visitor<'de> for TestVisitor {
type Value = Test;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("struct Test")
}
fn visit_map(self, mut map: V) -> Result
where V: MapAccess<'de>
{
let mut min = None;
let mut max = None;
let mut i = None;
while let Some(key) = map.next_key()? {
match key {
"min" => {
if min.is_some() {
return Err(de::Error::duplicate_field("min"));
}
min = Some(map.next_value()?);
}
"max" => {
if max.is_some() {
return Err(de::Error::duplicate_field("max"));
}
max = Some(map.next_value()?);
}
"i" => {
if i.is_some() {
return Err(de::Error::duplicate_field("i"));
}
i = Some(map.next_value()?);
}
_ => {
/* Ignore extra fields */
}
}
}
let min = min.ok_or_else(|| de::Error::missing_field("min"))?;
let max = max.ok_or_else(|| de::Error::missing_field("max"))?;
let i = i.ok_or_else(|| de::Error::missing_field("i"))?;
Ok(Test { i, team_size: TeamSize { min, max }})
}
}
const FIELDS: &'static [&'static str] = &["min", "max", "i"];
deserializer.deserialize_struct("Test", FIELDS, TestVisitor)
}
}
fn main() {
let t: Test = serde_json::from_str(r#"{"i": -2, "min": 2, "max": 5}"#).unwrap();
assert_eq!(t.i, -2);
assert_eq!(t.team_size.min, 2);
assert_eq!(t.team_size.max, 5);
}