gpt4 book ai didi

rust - 在 FromForm 中反序列化 JSON 时的生命周期

转载 作者:行者123 更新时间:2023-11-29 08:14:19 25 4
gpt4 key购买 nike

我无法理解这段代码的生命周期之间的关系。基本上,我有一个接收一些 x-www-form-urlencoded 的 Rocket API数据,只有一个键:json .这个键直观地包含一个 JSON 值,用百分比编码编码,结构为 Message<T>。 .

(我知道这是次优的 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> .

为了实际执行解码,我:

  1. 获取 "json"表单数据的关键字;
  2. URL-解码值;
  3. 解析值中包含的 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以粘贴和运行的方式(在 Playground 上不起作用,因为它依赖于 Rocket)。

据我了解:

  • &RawStrencoded有生命周期 'f .
  • A Stringurl_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 | | }
| |_^

我哪里出错了,我怎样才能正确返回反序列化的值?

最佳答案

This section of the Serde website covers Deserialize bounds in detail.


There are two main ways to write Deserialize trait bounds, whether on an impl block or a function or anywhere else.

  • <'de, T> where T: Deserialize<'de>

    This means "T can be deserialized from some lifetime." The caller gets to decide what lifetime that is. Typically this is used when the caller also provides the data that is being deserialized from, for example in a function like serde_json::from_str. In that case the input data must also have lifetime 'de, for example it could be &'de str.

  • <T> where T: DeserializeOwned

    This means "T can be deserialized from any lifetime." The callee gets to decide what lifetime. Usually this is because the data that is being deserialized from is going to be thrown away before the function returns, so T must not be allowed to borrow from it. In your case the data is coming from URL-decoding some input, and the decoded data is thrown away after deserializing T. Another common use of this bound is functions that deserialize from an IO stream, such as serde_json::from_reader.

    To say it more technically, the DeserializeOwned trait is equivalent to the higher-rank trait bound for<'de> Deserialize<'de>. The only difference is DeserializeOwned is more intuitive to read. It means T owns all the data that gets deserialized.

更换您的 T: Deserialize<'f>T: DeserializeOwned 绑定(bind)正确传达不允许 T 从URL 解码数据,因为 URL 解码数据不会超过 T。

关于rust - 在 FromForm 中反序列化 JSON 时的生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45783315/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com