use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::collections::HashMap; use std::error::Error; use std::fmt::Debug; use std::sync::LazyLock; use serde_flexitos::ser::require_erased_serialize_impl; use serde_flexitos::{serialize_trait_object, MapRegistry, Registry}; // Example trait pub trait ExampleObj: erased_serde::Serialize + Debug { fn key(&self) -> &'static str; fn get(&self) -> T; // Get some inner value typed by a generic, for example purposes. } // Example trait implementations #[derive(Clone, Serialize, Deserialize, Debug)] struct Foo(String); impl Foo { const STRING_KEY: &'static str = "Foo+String"; const USIZE_KEY: &'static str = "Foo+usize"; } impl ExampleObj for Foo { fn key(&self) -> &'static str { Self::STRING_KEY } fn get(&self) -> String { self.0.clone() } // Just gets its value as the generic type } impl ExampleObj for Foo { fn key(&self) -> &'static str { Self::USIZE_KEY } fn get(&self) -> usize { self.0.len() } } impl Into>> for Foo where Foo: ExampleObj, { fn into(self) -> Box> { Box::new(self) } } // Actually stores something of the generic type. #[derive(Clone, Serialize, Deserialize, Debug)] struct Bar(T); impl Bar { const KEY: &'static str = "Bar+String"; } impl Bar { const KEY: &'static str = "Bar+usize"; } impl ExampleObj for Bar { fn key(&self) -> &'static str { Self::KEY } fn get(&self) -> String { self.0.clone() } } impl ExampleObj for Bar { fn key(&self) -> &'static str { Self::KEY } fn get(&self) -> usize { self.0 } } impl Into>> for Bar where Bar: ExampleObj, { fn into(self) -> Box> { Box::new(self) } } // Registries static EXAMPLE_OBJ_STRING_REGISTRY: LazyLock>> = LazyLock::new(|| { let mut registry = MapRegistry::>::new("ExampleObj"); registry.register_type::(Foo::STRING_KEY); registry.register_type::>(Bar::::KEY); registry }); static EXAMPLE_OBJ_USIZE_REGISTRY: LazyLock>> = LazyLock::new(|| { let mut registry = MapRegistry::>::new("ExampleObj"); registry.register_type::(Foo::USIZE_KEY); registry.register_type::>(Bar::::KEY); registry }); // (De)serialize implementations impl<'a, T> Serialize for dyn ExampleObj + 'a { fn serialize(&self, serializer: S) -> Result where S: Serializer, { const fn __check_erased_serialize_supertrait>() { require_erased_serialize_impl::(); } serialize_trait_object(serializer, self.key(), self) } } impl<'de> Deserialize<'de> for Box> { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { EXAMPLE_OBJ_STRING_REGISTRY.deserialize_trait_object(deserializer) } } impl<'de> Deserialize<'de> for Box> { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { EXAMPLE_OBJ_USIZE_REGISTRY.deserialize_trait_object(deserializer) } } // Run serialization roundtrips fn main() -> Result<(), Box> { let foo = Foo("A".to_string()); let bar_usize = Bar(0); let bar_string = Bar("B".to_string()); { // `Vec>>` serialization roundtrip let examples: Vec>> = vec![Box::new(foo.clone()), Box::new(bar_usize.clone())]; let json = serde_json::to_string(&examples)?; println!("`Vec>>` serialized: {}", json); let roundtrip: Vec>> = serde_json::from_str(&json)?; println!("`Vec>>` deserialized: {:?}", roundtrip); } { // `HashMap>>` serialization roundtrip let mut examples = HashMap::>>::new(); examples.insert("foo".to_string(), Box::new(foo.clone())); examples.insert("bar".to_string(), Box::new(bar_string.clone())); let json = serde_json::to_string(&examples)?; println!("`HashMap>>` serialized: {}", json); let roundtrip: HashMap::>> = serde_json::from_str(&json)?; println!("`HashMap>>` deserialized: {:?}", roundtrip); } Ok(()) }