Пример:
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct S {
pub base_n: u8,
pub n: u8,
}
Хотелось бы, что бы в конфиге пользователю необходимо было указывать только n
поле, а base_n
при/после сериализации автоматически приравнивалось бы к n
.
У serde есть https://serde.rs/field-attrs.html#serdedefault и https://serde.rs/field-attrs.html#serdedefault--path, но они должны иметь сигнатуру fn() -> T
, т.е. не могут использовать значения из других полей структуры.
Единственное, что пока в голову приходит: дописать #[serde(default)]
к base_n
полю, что бы оно ставилось в ноль (давать Default всей структуре тоже не хочется), а потом, после сериализации, руками вызывать функцию init
, которая сделает с полями что нужно.
#[macro_use]
extern crate serde; // 1.0.78
extern crate serde_json; // 1.0.27
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct S {
#[serde(default)]
pub base_n: u8,
pub n: u8,
}
impl S {
fn from_str(s: &str) -> Self {
let mut this: S = serde_json::from_str(s).unwrap();
this.base_n = this.n;
this
}
}
fn main() {
let s = S::from_str(r#"{ "n": 3 }"#);
println!("s = {:?}", s);
}
Но тут система типов и автоматизация мало нам помогают соблюдать инварианты и появляется опасность когда-нибудь потом случайно десериализовать структуру без вызова init
а.