首页 > 解决方案 > 如何在`serde::ser::Serialize`的impl中跳过序列化?

问题描述

我想完全基于自定义实现中的某些值跳过序列化Serialize

impl Serialize for MyType {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        match &self.value {
            Action::Serialize => //serialize.serialize_struct(  etc...
            Action::NoSerialize => Ok(()) // <= Error. How do I return Ok and skip serialization ? 
       }
    }
}

错误消息读取

mismatched types
expected associated type `<S as mystuff::_::_serde::Serializer>::Ok`
         found unit type `()`rustcE0308
mod.rs(160, 22): consider constraining the associated type `<S as mystuff::_::_serde::Serializer>::Ok` to `()`: `<Ok = ()>`

但我不知道如何指定建议的约束<Ok = ()>

标签: rustserde

解决方案


这将取决于序列化程序。一些序列化程序(例如 Bincode)会跳过单位值,所以你可以只使用Serializer::serialize_unit(). 然而,其他人,如serde_json,将给出单位值,例如null

问题是,在某些情况下,序列化程序需要一个值。例如,如果您要序列化为 Json 映射(对象字面量),则没有值的键是没有意义的,但是您甚至在检查值之前就已经序列化了键。

因此,要一般地跳过值,您需要自定义包含该值的结构或集合的序列化,以确定要执行的正确操作。在某些情况下,这可能意味着为“父”类型编写自定义序列化,以使其了解需要跳过的内容。其他时候,您可以使用serde属性来自定义它:

#[derive(Serialize)]
pub struct Parent {
    #[serde(skip_serializing_if = "MyType::no_serialize")]
    pub my_value: MyType,
}

impl MyType {
    fn no_serialize(&self) -> bool {
        matches!(self, Action::NoSerialize)
    }
}

但我不知道如何指定建议的约束<Ok = ()>

在这种情况下,这个建议是一个红鲱鱼。这是您正在使用Ok的关联类型。Serializer这不是您可以更改的东西,将其更改为()将意味着创建一个序列化格式,该格式对于所有值都是空的。


推荐阅读