rust 如何对布尔字段使用skip_serializing_if跳过serde序列化

g6baxovj  于 2022-12-19  发布在  其他
关注(0)|答案(2)|浏览(206)

如果值为false,我希望跳过字段序列化。
在JSON中,这会将Foo序列化为{bar: true}{}

#[derive(Serialize)]
pub struct Foo {
    // This does not compile - bool::is_false does not exist
    #[serde(skip_serializing_if = "bool::is_false")]
    pub bar: bool,
}
wztqucjr

wztqucjr1#

好吧,根据塞尔德的记录:
第一个月
调用函数以确定是否跳过序列化此字段。给定函数必须可作为fn(&T) -> bool调用,尽管它可能是T的泛型函数
因此,您可以自己定义这样的函数,

fn is_false(b: &bool) -> bool { !b }

或者您可以在标准库中查找这样的函数。

  • 对于跳过真:Clone::clone
  • 对于跳过false:std::ops::Not::notPlayground

注意bool::not不起作用,因为您需要&bool上的Not impl:<&bool as std::ops::Not>::not

vmjh9lq9

vmjh9lq92#

为了只在布尔值为false时跳过序列化,您应该定义一个函数,当您想跳过序列化时,该函数返回true,如下所示:

fn is_false(b: &bool) -> bool {
    *b == false
}

然后像#[serde(skip_serializing_if = "is_false")]一样注解该结构体。
下面是完整的示例和playground link

use serde::Serialize;

#[derive(Serialize)]
pub struct Foo {
    #[serde(skip_serializing_if = "is_false")]
    pub bar: bool,
}

fn main() {
    let test1 = Foo { bar: true };
    let test2 = Foo { bar: false };

    println!("{}", serde_json::to_string(&test1).unwrap());
    println!("{}", serde_json::to_string(&test2).unwrap());
}

fn is_false(b: &bool) -> bool {
    *b == false
}

您也可以跳过序列化默认值,如下所示:

use serde::Serialize;

#[derive(Serialize)]
pub struct Foo {
    #[serde(default, skip_serializing_if = "is_default")]
    pub bar: bool,
}

fn main() {
    let test1 = Foo { bar: true };
    let test2 = Foo { bar: false };

    println!("{}", serde_json::to_string(&test1).unwrap());
    println!("{}", serde_json::to_string(&test2).unwrap());
}

fn is_default<T: Default + PartialEq>(t: &T) -> bool {
    t == &T::default()
}

这里是对应的playground

相关问题