使用 serde 实现两种(反)序列化格式

tob*_*svl 12 rust serde

我已经成功地用于serde_json反序列化和序列化 JSON。我的设置看起来有点像这样(非常简单):

use serde::{Deserialize, Serialize};
use serde_json;
use serde_with::skip_serializing_none;

#[skip_serializing_none]
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
struct Foo {
    #[serde(flatten)]
    bar: Option<Bar>,
    
    baz_quux: Option<u8>,
}

#[skip_serializing_none]
#[derive(Deserialize, Serialize)]
struct Bar {
    #[serde(rename = "plughXyzzySomeRandomStuff")]
    plugh_xyzzy: Option<u8>
}
Run Code Online (Sandbox Code Playgroud)

然后我实现了FromStrand Displayon Foo,它依次调用serde_json::from_strserde_json::to_string,以轻松(反)序列化该结构。

但是,我现在还想支持serde_ini将 INI 文件序列化(反序列化)到相同的 Rust 数据结构。但我真的不知道该怎么做。

结构本身很简单,但我的具体问题在于属性:

  • 这些键在 JSON 和 INI 格式中的命名方式不同(JSON 格式使用惯用的驼峰命名法,而 INI 则没有),因此我必须以其他方式解决#[serde(rename)]#[serde(rename_all)]属性,但我不确定在哪里或如何解决。
  • #[serde(flatten)] 似乎不适用于serde_ini全字符串值,它需要#[serde(deserialize_with="from_str)]"所有非字符串值的属性,但这显然只适用于 INI 值,而不适用于 JSON 值。

总而言之,我想我需要做的是重新实现这些属性,或者根据使用的 (De)Serializer 有条件地使用它们,但我对如何做到这一点感到困惑。

Pet*_*all 14

这是serde设计的一个限制。和Deserialize的实现有意地与和 的实现Serialize分开,这在选择不同格式和交换它们时提供了极大的灵活性和便利性。不幸的是,这意味着不可能针对不同的格式单独微调您的实现。SerializerDeserializerDeserializeSerialize

我之前完成此操作的方法是复制数据类型,以便我可以为每种格式配置它们,然后在它们之间提供零成本转换。

  • @tobiasvl impl from ,所有这些,rust 都会足够聪明。 (2认同)