我无法理解此代码生命周期之间的关系。基本上,我有一个Rocket API接收一些x-www-form-urlencoded
数据,只有一个密钥:json
。该键直观地包含结构Message<T>
的以百分比编码编码的JSON值。
(我知道这是次优的API设计,但这是逆向工程,所以我没有选择)
为了轻松地将From<Message<T>>
用作请求保护,我实施FromForm
。为此,我需要为FromForm<'f>
实现Message<T>
的任何T
实施Deserialize<'de>
。我将我的impl签名写为impl<'f, 'de, T> FromForm<'f> for Message<T> where T: Deserialize<'de>
。
要实际执行解码,我:
"json"
键; 尽快纾困。代码这样做(显式类型注释为读者带来方便):
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))
}
以粘贴并运行的方式A Gist demonstrating the problem(因为它依赖于Rocket而不能在Playground上运行)。
据我所知:
&RawStr
encoded
的有效期为'f
。String
由url_decode
创建serde_json
,直到功能结束&'x str
需要'x
,其中'de
不需要与205 | serde_json::from_str::<Self>(&json)
| ^^^^ does not live long enough
206 | .map_err(|e| MessageFormError::InvalidJson(e))
207 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'f as defined on the impl at 184:1...
--> src/transport.rs:184:1
|
184 | / impl<'f, T> FromForm<'f> for Message<T>
185 | | where T: Deserialize<'f>
186 | | {
187 | | type Error = MessageFormError;
... |
207 | | }
208 | | }
| |_^
重合,并返回一个值(因此它会一直存在到函数的末尾,因此它被退回了,超越了它)但似乎我的理解不正确:
// Large devices (desktops, less than 1200px)
@media (max-width: 1199px) { ... }
// Medium devices (tablets, less than 992px)
@media (max-width: 991px) { ... }
// Small devices (landscape phones, less than 768px)
@media (max-width: 767px) { ... }
// Extra small devices (portrait phones, less than 576px)
@media (max-width: 575px) { ... }
我出错了什么,如何正确返回反序列化值?
答案 0 :(得分:2)
This section of the Serde website covers Deserialize
bounds in detail.
有两种主要方式来编写
Deserialize
特征边界,无论如何 在impl块或函数或其他任何地方。
<强>
<'de, T> where T: Deserialize<'de>
强>这意味着“T可以从某些生命周期中反序列化。”调用者可以决定它的生命周期。通常使用它 当调用者还提供正在反序列化的数据时 例如,在类似的函数中
serde_json::from_str
。 在这种情况下,输入数据也必须具有生命周期'de
它可能是&'de str
。<强>
<T> where T: DeserializeOwned
强>这意味着“T可以从任何生命周期中反序列化。”被调用者可以决定生命周期。通常这是因为数据 正被反序列化的内容将在之前被抛弃 函数返回,所以不能允许T从中借用。 在你的 如果数据来自URL解码某些输入,则解码 反序列化T后数据被丢弃。这是另一种常见用法 bound是从IO流反序列化的函数,例如
serde_json::from_reader
从技术角度来说,
DeserializeOwned
特质相当于higher-rank trait boundfor<'de> Deserialize<'de>
。唯一的区别是DeserializeOwned
更多 直观易读。这意味着T拥有所有获得的数据 反序列化。
用T: Deserialize<'f>
替换T: DeserializeOwned
绑定
正确地告知T不允许从中借用
URL解码数据,因为URL解码数据不会比T更长。