无需自定义反序列化器,如何为含Weak的Rust结构体传入Arc完成反序列化?
无需自定义反序列化器给结构体注入Weak引用的方法
你可以通过两种简单方式实现需求,完全不需要编写自定义反序列化器或访问器:
方法一:利用serde的字段跳过属性
给SomeState中的b字段添加#[serde(skip_deserializing)]属性,让serde在反序列化时忽略这个字段,之后手动为其赋值为传入Arc的Weak引用:
use serde::Deserialize; use std::sync::{Arc, Weak}; use serde_json; struct SomeGlobal; #[derive(Deserialize)] struct SomeState { pub a: i32, #[serde(skip_deserializing)] pub b: Weak<SomeGlobal>, } fn magic_deserialize(value: serde_json::Value, g: Arc<SomeGlobal>) -> Result<SomeState, serde_json::Error> { let mut state = serde_json::from_value(value)?; state.b = Arc::downgrade(&g); Ok(state) } #[test] fn example() { let g = Arc::new(SomeGlobal); let value = serde_json::json!({ "a": 5 }); let state = magic_deserialize(value, g.clone()).unwrap(); assert_eq!(state.a, 5); assert!(state.b.upgrade().is_some()); }
这个属性会告诉serde不要尝试从JSON输入中读取b字段,反序列化完成后我们直接替换成需要的Weak引用即可。
方法二:使用临时结构体过渡
定义一个只包含需要从JSON反序列化字段的临时结构体,反序列化完成后用它的数据和传入的Arc构造最终的SomeState:
use serde::Deserialize; use std::sync::{Arc, Weak}; use serde_json; struct SomeGlobal; #[derive(Deserialize)] struct SomeState { pub a: i32, pub b: Weak<SomeGlobal>, } #[derive(Deserialize)] struct TempState { pub a: i32, } fn magic_deserialize(value: serde_json::Value, g: Arc<SomeGlobal>) -> Result<SomeState, serde_json::Error> { let temp_state = serde_json::from_value(value)?; Ok(SomeState { a: temp_state.a, b: Arc::downgrade(&g), }) } #[test] fn example() { let g = Arc::new(SomeGlobal); let value = serde_json::json!({ "a": 5 }); let state = magic_deserialize(value, g.clone()).unwrap(); assert_eq!(state.a, 5); assert!(state.b.upgrade().is_some()); }
这种方式拆分了反序列化和结构体构造的逻辑,适合结构体字段较多的场景。
内容的提问来源于stack exchange,提问作者A.Z.
相关产品推荐
相关产品推荐

