I'm using Rust and Serde. Suppose I have a struct that wants to keep a copy of the JSON data that created it, maybe so that it can re-send that same JSON elsewhere without having to re-serialize. (And it's not as simple as just keeping a copy of the original JSON data, since the struct might be inside more JSON data.) Example:
#[derive(Deserialize)]
struct LargerStruct {
value: i32,
inner: InnerStruct,
}
#[derive(Deserialize)]
struct InnerStruct {
this_json: String,
inner_value: i32,
}
fn main() {
let json = r#"
{
"value": 42,
"inner": { "inner_value": 100 }
}
"#;
let val: LargerStruct = // ???
assert_eq!(&val.inner.this_json, r#"{ "inner_value": 100 }"#);
}
What might fill the ???
comment?
/*
[dependencies]
serde.version = "*"
serde.features = ["derive"]
serde_json.version = "*"
serde_json.features = ["raw_value"]
*/
use serde::*;
use serde_json::value::RawValue;
#[derive(Deserialize)]
struct LargerStruct {
value: i32,
inner: InnerStruct,
}
struct InnerStruct {
this_json: String,
inner_value: i32,
}
impl<'de> Deserialize<'de> for InnerStruct {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let this_json: Box<RawValue> = Deserialize::deserialize(deserializer)?;
#[derive(Deserialize)]
struct InnerStruct {
inner_value: i32,
}
let this: InnerStruct =
serde_json::from_str(this_json.get()).map_err(serde::de::Error::custom)?;
Ok(Self{
this_json: this_json.get().to_string(),
inner_value: this.inner_value,
})
}
}
fn main() {
let json = r#"
{
"value": 42,
"inner": { "inner_value": 100 }
}
"#;
let val: LargerStruct = serde_json::from_str(json).unwrap();
assert_eq!(&val.inner.this_json, r#"{ "inner_value": 100 }"#);
}
You can use the serde_json::value::RawValue
type to capture the original JSON in raw form. The code uses a custom Deserialize
implementation for InnerStruct
to achieve the goal of capturing the JSON and deserialize. It deserializes the struct, by calling serde_json
again on the captured JSON inside the Deserialize
implementation. This is necessary, since the deserializer
is consumed after deserializing the RawValue
.