Serde:使用容器#[serde(default)],但带有一些必填字段

wis*_*sha 10 rust serde

我有一个使用容器#[serde(default)]属性的结构。

但是有一个字段是必需的(如果传入数据中不存在该字段,则解串器应该出错而不是回退到默认值)。

#[serde(default)]
#[derive(Serialize, Deserialize)]
struct Example {
  important: i32, // <-- I want this field to be required.
  a: i32, //  <-- If this field isn't in the incoming data, fallback to the default value.
  b: i32, //  <-- If this field isn't in the incoming data, fallback to the default value.
  c: i32, //  <-- If this field isn't in the incoming data, fallback to the default value.
}
Run Code Online (Sandbox Code Playgroud)

编辑:

下面的信息不正确。field属性不采用结构类型的默认值,而是采用每个字段的类型的默认值#[serde(default)] (即impl Default for Example未使用。impl Default for i32已使用)。

结束编辑。

我可以像这样使用字段#[serde(default)]属性:

#[derive(Serialize, Deserialize)]
struct Example {
  important: i32,
  #[serde(default)]
  a: i32,
  #[serde(default)]
  b: i32,
  #[serde(default)]
  c: i32,
}
Run Code Online (Sandbox Code Playgroud)

所以important将是必需的,而abc将具有默认值。

但是,复制粘贴#[serde(default)]除一个字段之外的所有字段似乎并不是一个好的解决方案(我的结构有大约 10 个字段)。有没有更好的办法?

小智 18

根据您的编辑,您可以用来#[serde(default = "path")]设置每个字段的默认值。该路径指向返回该字段的默认值的函数。

参考: https: //serde.rs/field-attrs.html

例子:

const A_DEFAULT: i32 = 1;
const B_DEFAULT: i32 = 2;
const C_DEFAULT: i32 = 3;

#[derive(Serialize, Deserialize)]
struct Example {
  important: i32,
  #[serde(default = "a_default")]
  a: i32,
  #[serde(default = "b_default")]
  b: i32,
  #[serde(default = "c_default")]
  c: i32,
}

fn a_default() -> i32{
  A_DEFAULT
}
fn b_default() -> i32{
  B_DEFAULT
}
fn c_default() -> i32{
  C_DEFAULT
}
Run Code Online (Sandbox Code Playgroud)

  • 更新:您现在还可以使用 const fns 来实现:`const fn _default_true() -&gt; bool { true }`,然后`#[serde(default = "_default_true")] pub enable: bool,`。 (2认同)