【问题标题】:Using serde for two (de)serialization formats将 serde 用于两种(反)序列化格式
【发布时间】:2021-10-23 19:29:29
【问题描述】:

我已成功使用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>
}

然后我在Foo 上实现了FromStrDisplay,它们分别调用serde_json::from_strserde_json::to_string,以轻松(反)序列化结构。

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

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

  • 键在 JSON 和 INI 格式中的命名不同(JSON 格式使用习惯的驼峰式,而 INI 没有),所以我必须以其他方式解决 #[serde(rename)]#[serde(rename_all)] 属性,但是我不确定在哪里或如何。
  • #[serde(flatten)] doesn't seem to workserde_ini 的全字符串值,所有非字符串值都需要 #[serde(deserialize_with="from_str)]" 属性,但这显然只适用于 INI 值,而不适用于 JSON 值。

总而言之,我想我需要做的是重新实现这些属性,或者根据使用的 (De)Serializer 有条件地使用它们,但我不知道该怎么做。

【问题讨论】:

标签: rust serde


【解决方案1】:

这是serde 设计的限制。 DeserializeSerialize 实现有意与 SerializerDeserializer 实现分开,这在选择不同格式和交换它们时提供了极大的灵活性和便利性。不幸的是,这意味着无法针对不同格式单独微调 DeserializeSerialize 实现。

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

【讨论】:

  • 谢谢!我想到了这个主意。很高兴这不是完全疯狂(我只是希望有一种更优雅的方式)。但是,在两个结构之间提供零成本转换的惯用方法是什么?
  • @tobiasvl:假设结构具有相同的布局,我认为编译器只能保证它们是否为repr(C),我建议使用union
  • @tobiasvl impl from and that all, rust 将足够聪明。
  • @Stargateur 这真的是零成本吗?有趣的!这就是我最终做的,所以那很酷。虽然有很多代码重复(每个结构和枚举基本上都有两个),但如果这无济于事,那么我可以接受。至少像魅力一样工作!谢谢!
猜你喜欢
  • 2023-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
相关资源
最近更新 更多