rust struct with #[serde(flatten)] loses data when converting to JsValue
tracing::info!("to json {:?}", serde_json::to_string(&v).unwrap());
tracing::info!("to value {:?}", serde_wasm_bindgen::to_value(&v).unwrap());
to json "{\"method\":\"__stream/expmple\",\"params\":{\"data\":\"hi i'm server(2)\"}}"
to value JsValue(Object({"method":"__stream/expmple","params":{}}))
https://github.com/modelcontextprotocol/rust-sdk/blob/main/crates/rmcp/src/model.rs#L372
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
pub struct Notification<M = String, P = JsonObject> {
pub method: M,
pub params: P,
/// extensions will carry anything possible in the context, including [`Meta`]
///
/// this is similar with the Extensions in `http` crate
#[cfg_attr(feature = "schemars", schemars(skip))]
pub extensions: Extensions,
}
impl<M, R> Serialize for Notification<M, R>
where
M: Serialize,
R: Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let extensions = &self.extensions;
let _meta = extensions.get::<Meta>().map(Cow::Borrowed);
Proxy::serialize(
&Proxy {
method: &self.method,
params: WithMeta {
_rest: &self.params,
_meta,
},
},
serializer,
)
}
}
#[derive(Serialize, Deserialize)]
struct WithMeta<'a, P> {
#[serde(skip_serializing_if = "Option::is_none")]
_meta: Option<Cow<'a, Meta>>,
#[serde(flatten)]
_rest: P,
}
#[derive(Serialize, Deserialize)]
struct Proxy<'a, M, P> {
method: M,
params: WithMeta<'a, P>,
}
Unfortunately, it's a known long-standing issue in Serde itself. https://github.com/serde-rs/serde/issues/1183
Nothing we can do on specific deserializer side.
Thanks, But the problem I described occurs in the serializer.
You are right, sorry, I overlooked that.
Can you provide a minimal repro that works in isolation? Eg in your code snippet it's unclear where data field comes from, ideally I'd like so see all struct with no 3rd-party deps.
https://github.com/kirito41dd/serde-wasm-bindgen-issue
@RReverser thanks.
I suspect this has to do with our checks where we tried to ensure the JsValue specific conversion only works with serde-wasm-bindgen and doesn't try to produce gibberish with other formats... But serde flatten generating serialize_map instead of serialize_struct disrupts that.