I'm sorry, but I don't understand your problem. I feel like the solution @H2CO3 gave you here:
should work in this case, too. Maybe your real-world code has some extra difficulties not covered in your example? Even with typetag
, using the #[serde(untagged)]
attribute on crate_new::MyStruct
allows you to deserialize crate1_box_str
as Box<dyn crate_new::MyTrait>
:
/*
[dependencies]
serde = { version = "1", features = ["derive"] }
serde_json = "1"
typetag = "*"
*/
pub mod crate_old {
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MyStruct(
#[serde()]
pub usize
);
#[typetag::serde(tag = "MyTrait", content = "value")]
pub trait MyTrait {}
#[typetag::serde]
impl MyTrait for MyStruct {}
}
pub mod crate_new {
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum MyStruct {
RealStruct(usize),
}
#[typetag::serde(tag = "MyTrait", content = "value")]
pub trait MyTrait {}
#[typetag::serde]
impl MyTrait for MyStruct {}
}
fn main() {
let crate1_box: Box<dyn crate_old::MyTrait> = Box::new(crate_old::MyStruct(10));
let crate1_box_str = serde_json::to_string(&crate1_box).unwrap();
assert_eq!(crate1_box_str, r#"{"MyTrait":"MyStruct","value":10}"#);
let crate2_box: Box<dyn crate_new::MyTrait> = Box::new(crate_new::MyStruct::RealStruct(10));
let crate2_box_str = serde_json::to_string(&crate2_box).unwrap();
assert_eq!(crate2_box_str, crate1_box_str);
let crate2_box: Box<dyn crate_new::MyTrait> = serde_json::from_str(&crate1_box_str).unwrap();
}