I wouldn’t necessarily say that this is a limitation of Serde. It is a limitation of the universe, and a huge benefit of Serde that it behaves sensibly in this case rather than handing you a use-after-free.
let v: Value = serde_json::from_str(j)?;
let m: Mmlinford = serde_json::from_value(v)?;
In this code, ownership of the Value
is moved into from_value
and the value is destroyed before from_value
returns. That means we must not hand out any &str
that the caller could hold on to longer than the duration of from_value
.
The same thing works if you deserialize from the Value
without immediately destroying it. This way the deserializer is free to hand out &str
that live as long as the Value
.
let v: Value = serde_json::from_str(j).unwrap();
let m = Mmlinford::deserialize(&v).unwrap();
Alternatively you could keep the from_value
as is, and change de_from_str
to use the type system to guarantee that the &str
is not held on to longer than the call to from_value
. This is what Visitor
s do in Serde.
struct BoolFromStr;
impl<'de> Visitor<'de> for BoolFromStr {
type Value = bool;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string containing \"true\" or \"fales\"")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
where E: de::Error
{
bool::from_str(s).map_err(de::Error::custom)
}
}
// instead of `<&str>::deserialize(deserializer)`
deserializer.deserialize_str(BoolFromStr)