Kro*_*tan 2 rust serde rust-rocket
我无法理解这段代码的生命周期之间的关系。基本上,我有一个接收一些x-www-form-urlencoded数据的 Rocket API,只有一个键:json. 这个键直观地包含一个 JSON 值,用百分比编码,一个 struct Message<T>。
(我知道这是次优的 API 设计,但这是逆向工程工作,所以我别无选择)
为了方便地用作请求保护器From<Message<T>>,我正在实现FromForm. 为此,我需要FromForm<'f>为任何Message<T>where Timplements 实现Deserialize<'de>。我将我的 impl 签名写为impl<'f, 'de, T> FromForm<'f> for Message<T> where T: Deserialize<'de>.
为了实际执行解码,我:
"json"表单数据的key;尽快脱险。这样做的代码(为方便读者使用显式类型注释):
fn from_form(items: &mut FormItems<'f>, strict: bool) -> Result<Self, Self::Error> {
// Get JSON field
let encoded: Option<&RawStr> = items.find(|&(k, _)| k.as_str() == "json")
.map(|(_, v)| v);
if let None = encoded {
return Err(MessageFormError::MissingJsonKey);
}
// Decode URL-string
let decoded: Result<String, Utf8Error> = encoded.unwrap().url_decode();
if let Err(e) = decoded {
return Err(MessageFormError::InvalidUrl(e));
}
// Parse JSON
let json: String = decoded.unwrap();
serde_json::from_str::<Self>(&json) // Line 205
.map_err(|e| MessageFormError::InvalidJson(e))
}
Run Code Online (Sandbox Code Playgroud)
以粘贴和运行方式演示问题的 Gist(在 Playground 上不起作用,因为它依赖于 Rocket)。
我认为:
&RawStr中encoded有寿命'f。String是由它创建的url_decode,它一直存在到函数结束serde_json需要一个&'x strwhere'x不需要与 重合'de,并返回一个值(所以它一直存在到函数的末尾,并且因为它被返回,被移到了它之外)但似乎我的理解是不正确的:
fn from_form(items: &mut FormItems<'f>, strict: bool) -> Result<Self, Self::Error> {
// Get JSON field
let encoded: Option<&RawStr> = items.find(|&(k, _)| k.as_str() == "json")
.map(|(_, v)| v);
if let None = encoded {
return Err(MessageFormError::MissingJsonKey);
}
// Decode URL-string
let decoded: Result<String, Utf8Error> = encoded.unwrap().url_decode();
if let Err(e) = decoded {
return Err(MessageFormError::InvalidUrl(e));
}
// Parse JSON
let json: String = decoded.unwrap();
serde_json::from_str::<Self>(&json) // Line 205
.map_err(|e| MessageFormError::InvalidJson(e))
}
Run Code Online (Sandbox Code Playgroud)
我出了什么问题,如何正确返回反序列化的值?
Serde 网站的这一部分Deserialize详细介绍了边界。
有两种主要的方法来编写
Deserializetrait bound,无论是在 impl 块、函数还是其他任何地方。
<'de, T> where T: Deserialize<'de>这意味着“T 可以从某个生命周期反序列化”。调用者可以决定那是什么生命周期。通常,当调用者还提供正在从中反序列化的数据时,例如在像
serde_json::from_str. 在这种情况下,输入数据也必须具有生命周期'de,例如它可能是&'de str.
<T> where T: DeserializeOwned这意味着“T 可以从任何生命周期反序列化”。被调用者可以决定什么生命周期。通常这是因为反序列化的数据将在函数返回之前被丢弃,所以不能允许 T 借用它。在您的情况下,数据来自对某些输入进行 URL 解码,并且在反序列化 T 后将解码的数据丢弃。此绑定的另一个常见用途是从 IO 流反序列化的函数,例如
serde_json::from_reader.更专业地说,
DeserializeOwned特质相当于更高等级的特质 boundfor<'de> Deserialize<'de>。唯一的区别是DeserializeOwned阅读起来更直观。这意味着 T 拥有所有反序列化的数据。
T: Deserialize<'f>用T: DeserializeOwned
正确替换你的绑定表明 T 不允许从 URL 解码的数据中借用,因为 URL 解码的数据不会超过 T。
| 归档时间: |
|
| 查看次数: |
552 次 |
| 最近记录: |