1

I have a struct that I can only deserialize if I use the serde_stacker. So in order to deserialize the struct Bar I need to first convert it to a serde_json::value::Value type that is used to hold JSON values, and then convert it to the desired Bar type.

const SIZE: usize = 30000;

#[derive(Clone, Debug, Serialize, Deserialize)]
struct Foo {
    #[serde(with = "BigArray")]
    vals: [bool; SIZE],
}

#[derive(Clone, Debug, Serialize, Deserialize)]
struct Bar {
    field0: Foo,
}

impl Bar {
    fn custom_deserialization_test(instance: Bar) {
        let json = serde_json::to_string(&instance).unwrap();
        let mut deserializer: serde_json::Deserializer<serde_json::de::StrRead> =
            serde_json::Deserializer::from_str(&json);
        let deserializer: serde_stacker::Deserializer<
            &mut serde_json::Deserializer<serde_json::de::StrRead>,
        > = serde_stacker::Deserializer::new(&mut deserializer);
        let value: Value = Value::deserialize(deserializer).unwrap();
        let target: Bar = from_value(value).unwrap();
    }
}

My question is: How do I overwrite Bar's deserialize method to use the serde_stacker deserializer instead of the regular serde_json deserializer as I do above?

I might need some kind of wrapper but the from_value function call on the last line of code uses the derived deserialize method of Bar to convert from the JSON object to type Bar.

Thorkil Værge
  • 2,727
  • 5
  • 32
  • 48

1 Answers1

1

The Bar::deserialize function is generic over the Deserializer used. This means you can use serde_stacker::Deserializer instead of a Deserializer from serde_json. Your posted code snippet already shows how to use serde_stacker on the Value type. You only need to replace it with Bar.

impl Bar {
    fn custom_deserialization_test(instance: Bar) {
        let json = serde_json::to_string(&instance).unwrap();
        let mut deserializer: serde_json::Deserializer<serde_json::de::StrRead> =
            serde_json::Deserializer::from_str(&json);
        let deserializer: serde_stacker::Deserializer<
            &mut serde_json::Deserializer<serde_json::de::StrRead>,
        > = serde_stacker::Deserializer::new(&mut deserializer);
        let target = Bar::deserialize(deserializer).unwrap();
    }
}
jonasbb
  • 2,131
  • 1
  • 6
  • 25
  • It's not possible to achieve this with fewer lines, or wrapping it in an `impl`? – Thorkil Værge Jun 20 '22 at 07:54
  • 1
    Using fewer lines is not really possible. You always need to 1) create JSON deserializer, 2) wrap it in the `serde_stacker` deserializer, 3) call `Bar::deserialize`. You can remove the type annotations for the local variables, saving some lines by inferring the types. The code is already in an `impl`, so that works too. – jonasbb Jun 20 '22 at 12:01