Rust字符串反序列化生命周期问题的最佳解决方法
问题原因
你代码里的生命周期错误本质是Deserialize<'a>约束允许反序列化结果直接借用输入JSON字符串的内存,但你代码中str_json是update方法内部的局部变量,方法执行结束就会被销毁释放,如果T持有对str_json的引用就会成为悬垂引用,Rust生命周期检查器会直接阻止这类不安全代码编译。另外你写的update方法缺少&mut self参数,本身也无法访问修改实例的data字段。
最佳解决方案
绝大多数业务场景下,我们都希望反序列化得到的对象完全持有自身数据、不依赖源JSON字符串的生命周期,这时候直接把泛型约束从Deserialize<'a>换成DeserializeOwned即可。DeserializeOwned是serde提供的专门适配所有权场景的约束,等价于「对于任意生命周期'de,类型T都实现Deserialize<'de>」,不会把T的生命周期和局部短生命周期的字符串绑定,从根源上避免悬垂引用问题。
修正后的可运行代码如下:
use serde::de::DeserializeOwned; use serde_json; struct S1<T> { pub data: T } impl<T> S1<T> where T: DeserializeOwned { fn update(&mut self) { let str_json = String::new(); // 实际场景为从文件读取到的JSON字符串 self.data = serde_json::from_str(&str_json).unwrap(); } }
如果你确实有零拷贝反序列化的需求,需要反序列化结果直接借用源字符串数据,就不能把JSON字符串作为update的局部变量,需要把字符串的所有权转移到S1结构体中存储,保证字符串的生命周期长于data中持有的引用,再给结构体和实现块标注匹配的生命周期参数即可。这类场景需要手动维护生命周期关系,容易出错,非必要不选用。
内容的提问来源于stack exchange,提问作者Martin Ayvazyan
相关产品推荐
相关产品推荐

