Hi, I would like to have a struct with one of its members using borrowed data from a JSON document. The member in question attributes
can hold any valid JSON (other members are defined by a schema). I looked around and I found this topic on zero-copy json with serde, which led me to the serde_json_borrow crate. serde_json_borrow has a borrowed Value type, which does what I need.
Simple deserialization directly into a borrowed value works well:
let m_value: serde_json_borrow::Value = serde_json::from_str(json_str).unwrap();
However, when I include the borrowed Value in a struct, I'm not able to deserialize, because it seems that the data with lifetime 'a
does not outlive the lifetime of the deserializer 'de
.
I think I have to mark the input data with lifetime 'a
somehow, and my first attempt was this (which didn't work):
pub fn deserialize_with_borrow<'a>(json_str: &'a str) -> Model<'a> {
let m: Model = serde_json::from_str(json_str).unwrap();
m
}
Then I thought I somehow need to tell the deserializer to return the data with lifetime 'a
, and that is where I am at currently.
Below is a reproducible example. Sorry, no playground link because there no serde_json_borrow there.
use serde::de::Visitor;
use serde::{Deserialize, Serialize};
use serde_json_borrow::Value;
use serde_json::from_str;
#[derive(Debug, Deserialize, Serialize)]
pub struct Model<'a> {
#[serde(deserialize_with = "deserialize_attributes")]
pub attributes: Option<Attributes<'a>>,
}
type Attributes<'a> = serde_json_borrow::Value<'a>;
pub fn deserialize_attributes<'de, 'a: 'de, D>(
deserializer: D,
) -> std::result::Result<Option<Attributes<'a>>, D::Error>
where
D: serde::de::Deserializer<'de>,
{
let s = serde_json_borrow::Value::deserialize(deserializer)?;
Ok(Some(s))
}
#[test]
fn test() {
let json_str = r#"{ "attributes": {
"string": "value1",
"int": 42,
"object": { "float": 42.1 },
"array": ["item1", "item2"]
} }"#;
// This works
let m_value: serde_json_borrow::Value = serde_json::from_str(json_str).unwrap();
// Lifetime error, `'a` must outlive `'de`
let m: Model = serde_json::from_str(json_str).unwrap();
println!("{:?}", m);
}
I'm getting this error:
|
14 | pub fn deserialize_attributes<'de, 'a: 'de, D>(
| --- -- lifetime `'a` defined here
| |
| lifetime `'de` defined here
...
21 | Ok(Some(s))
| ^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'de`
|
Does this mean that I need to manually implement Deserialize and somehow include the lifetime 'a
in the return type? Or am I missing something else?