反序列化通用结构上的特征绑定
Deserialize trait bound on generic struct
我想通过 serde_json
为通用结构构建一个解析器,这是简化的逻辑。它会产生一个错误:“src
的寿命不够长”。
但为什么这会导致生命周期不够长的错误?
有什么办法可以解决吗,或者根本不建议这样写代码?
use serde_json;
use serde::Deserialize;
use std::marker::PhantomData;
#[derive(Default)]
struct Parser<'de, P:Deserialize<'de>>{
phantom1: PhantomData<&'de ()>,
phantom2: PhantomData<P>,
}
impl<'de, P:Deserialize<'de>> Parser<'de,P>{
fn parse(&self, src:&'de String){
serde_json::from_str::<P>(&src).unwrap();
}
}
#[derive(Default)]
struct OutterParser<'de, P:Deserialize<'de>>{
parser: Parser<'de, P>
}
impl<'de, P:Deserialize<'de>> OutterParser<'de,P>{
fn read_and_parse(&self){
let src = String::from(r#""""#);
self.parser.parse(&src);
}
}
fn main(){
let parser = OutterParser::<String>::default();
parser.read_and_parse();
}
编辑:
感谢凯文的回答。我曾经以为'de lifetime会在本地parse
函数中自动导出为lifetime。从本地 &src
构建 P
结构后,可以删除 src
。
现在我知道如果没有明显的注释,函数参数的生命周期将小于 'de
。
但是如果函数签名修改为fn parse(&self, &'de str)
,'de
会进一步向上传播,这不是我想要的。
P: Deserialize<'de>
表示反序列化为 P
类型的值需要输入数据,该数据必须至少存在 'de
.
fn parse(&self, src:String){
serde_json::from_str::<P>(&src).unwrap();
相反,您提供了对局部变量 src
的引用,该变量将在 parse
函数的末尾删除,因此肯定 更短 比 'de
.
为了不出现这个问题,您必须定义 parse
使其接受对 'de
:[=20 有效的 reference =]
fn parse(&self, src: &'de str) {
在另一个问题中找到答案:)
更简单的解决方法是使用 DeserializeOwned
...
use serde_json;
use serde::de::DeserializeOwned;
use std::marker::PhantomData;
#[derive(Default)]
struct Parser<P:DeserializeOwned>{
phantom2: PhantomData<P>,
}
impl<P:DeserializeOwned> Parser<P>{
fn parse(&self, src:&String){
serde_json::from_str::<P>(&src).unwrap();
}
}
#[derive(Default)]
struct OutterParser<P:DeserializeOwned>{
parser: Parser<P>
}
impl<P:DeserializeOwned> OutterParser<P>{
fn read_and_parse(&self){
let src = String::from(r#""""#);
self.parser.parse(&src);
}
}
fn main(){
let parser = OutterParser::<String>::default();
parser.read_and_parse();
}
我想通过 serde_json
为通用结构构建一个解析器,这是简化的逻辑。它会产生一个错误:“src
的寿命不够长”。
但为什么这会导致生命周期不够长的错误?
有什么办法可以解决吗,或者根本不建议这样写代码?
use serde_json;
use serde::Deserialize;
use std::marker::PhantomData;
#[derive(Default)]
struct Parser<'de, P:Deserialize<'de>>{
phantom1: PhantomData<&'de ()>,
phantom2: PhantomData<P>,
}
impl<'de, P:Deserialize<'de>> Parser<'de,P>{
fn parse(&self, src:&'de String){
serde_json::from_str::<P>(&src).unwrap();
}
}
#[derive(Default)]
struct OutterParser<'de, P:Deserialize<'de>>{
parser: Parser<'de, P>
}
impl<'de, P:Deserialize<'de>> OutterParser<'de,P>{
fn read_and_parse(&self){
let src = String::from(r#""""#);
self.parser.parse(&src);
}
}
fn main(){
let parser = OutterParser::<String>::default();
parser.read_and_parse();
}
编辑:
感谢凯文的回答。我曾经以为'de lifetime会在本地parse
函数中自动导出为lifetime。从本地 &src
构建 P
结构后,可以删除 src
。
现在我知道如果没有明显的注释,函数参数的生命周期将小于 'de
。
但是如果函数签名修改为fn parse(&self, &'de str)
,'de
会进一步向上传播,这不是我想要的。
P: Deserialize<'de>
表示反序列化为 P
类型的值需要输入数据,该数据必须至少存在 'de
.
fn parse(&self, src:String){
serde_json::from_str::<P>(&src).unwrap();
相反,您提供了对局部变量 src
的引用,该变量将在 parse
函数的末尾删除,因此肯定 更短 比 'de
.
为了不出现这个问题,您必须定义 parse
使其接受对 'de
:[=20 有效的 reference =]
fn parse(&self, src: &'de str) {
在另一个问题中找到答案:)
更简单的解决方法是使用 DeserializeOwned
...
use serde_json;
use serde::de::DeserializeOwned;
use std::marker::PhantomData;
#[derive(Default)]
struct Parser<P:DeserializeOwned>{
phantom2: PhantomData<P>,
}
impl<P:DeserializeOwned> Parser<P>{
fn parse(&self, src:&String){
serde_json::from_str::<P>(&src).unwrap();
}
}
#[derive(Default)]
struct OutterParser<P:DeserializeOwned>{
parser: Parser<P>
}
impl<P:DeserializeOwned> OutterParser<P>{
fn read_and_parse(&self){
let src = String::from(r#""""#);
self.parser.parse(&src);
}
}
fn main(){
let parser = OutterParser::<String>::default();
parser.read_and_parse();
}