leo*_*ion 4 yaml lifetime rust deserialization serde
我有这些结构:
#[derive(Debug, Serialize, Deserialize)]
pub struct GGConf<'a> {
#[serde(alias = "ssh")]
#[serde(rename = "ssh")]
#[serde(default)]
#[serde(borrow)]
pub ssh_config: Option<SSHConfig<'a>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SSHConfig<'a> {
#[serde(alias = "privateKey")]
#[serde(rename = "privateKey")]
private_key: &'a str,
username: &'a str,
}
Run Code Online (Sandbox Code Playgroud)
当我从 YAML 文件读取时发生反序列化:
let mut config: GGConf = serde_yaml::from_reader(file)?;
Run Code Online (Sandbox Code Playgroud)
在编译时,我收到一个错误:
#[derive(Debug, Serialize, Deserialize)]
pub struct GGConf<'a> {
#[serde(alias = "ssh")]
#[serde(rename = "ssh")]
#[serde(default)]
#[serde(borrow)]
pub ssh_config: Option<SSHConfig<'a>>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SSHConfig<'a> {
#[serde(alias = "privateKey")]
#[serde(rename = "privateKey")]
private_key: &'a str,
username: &'a str,
}
Run Code Online (Sandbox Code Playgroud)
我隐约明白 serde 反序列化也有生命周期'de,编译器混淆了我为它指定的生命周期?如果我错了,请纠正我。
我目前如何正确地将 YAML 反序列化为两个结构?有什么我在这里遗漏或误解的吗?
我查看了如何使用 actix-web 的 Json 类型解决“serde::Deserialize 的实现不够通用”?,但我不能使用拥有的类型。我需要它是借来的类型。
我将尝试为此编写一个游乐场示例。
这是不可能的; 您必须使用拥有的数据而不是引用。
这是一个最小的例子:
use serde::Deserialize; // 1.0.104
#[derive(Debug, Deserialize)]
pub struct SshConfig<'a> {
username: &'a str,
}
fn example(file: impl std::io::Read) {
serde_yaml::from_reader::<_, SshConfig>(file);
}
Run Code Online (Sandbox Code Playgroud)
use serde::Deserialize; // 1.0.104
#[derive(Debug, Deserialize)]
pub struct SshConfig<'a> {
username: &'a str,
}
fn example(file: impl std::io::Read) {
serde_yaml::from_reader::<_, SshConfig>(file);
}
Run Code Online (Sandbox Code Playgroud)
如果您查看 的定义serde_yaml::from_reader,您会发现它仅限于反序列化拥有的数据:
pub fn from_reader<R, T>(rdr: R) -> Result<T>
where
R: Read,
T: DeserializeOwned,
// ^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)
这同样适用于serde_json::from_reader并且可能任何等效的功能。
当有数据要引用时,您只能反序列化包含引用的类型。实现Readtrait 的东西只能保证它可以将一些字节复制到用户提供的缓冲区中。由于该from_reader函数不接受该缓冲区作为参数,因此任何缓冲区都将在 退出时被销毁,从而from_reader使引用无效。
也可以看看:
如果您必须使用引用(在许多情况下并非如此),您将需要:
from_str代替from_readerfrom_reader从某个地方(任何实现 Read 特征的地方)获取数据流 - 它不存储数据,这意味着没有任何东西拥有数据,因此您不能在结构中引用该数据。换句话说,from_reader需要一个临时的数据流,因此需要一个地方来存储数据。
另一个复杂因素是serde_yaml(至少对于版本 0.8.11)不支持零拷贝反序列化:
https://docs.rs/serde_yaml/0.8.11/serde_yaml/fn.from_str.html
Run Code Online (Sandbox Code Playgroud)pub fn from_str<T>(s: &str) -> Result<T> where T: DeserializeOwned,...
YAML 目前不支持零拷贝反序列化。
将其与比方说 相比serde_json,它执行以下操作:
https://docs.rs/serde_json/1.0.50/serde_json/de/fn.from_str.html
Run Code Online (Sandbox Code Playgroud)pub fn from_str<'a, T>(s: &'a str) -> Result<T> where T: Deserialize<'a>,
因此,至少serde_json可以from_str从拥有的缓冲区中使用类似的东西,这将允许您在结构中使用引用(但这不适用于serde_yaml当前)
pub fn from_str<T>(s: &str) -> Result<T> where
T: DeserializeOwned,
Run Code Online (Sandbox Code Playgroud)
完全取决于您所关心的是什么,这可能比在您的结构中存储字符串效率低(例如,如果example.json1MB 大,并且您只提取一个字段 - 上面的代码会将整个 1MB 字符串存储在内存中,只有几个字节的文本可访问)。
| 归档时间: |
|
| 查看次数: |
3526 次 |
| 最近记录: |