rust - 我如何支持 Serde 枚举的未知值或其他值?

标签 rust serde

我有一个 JSON API,它返回一个如下所示的对象:

{
  "PrivatePort": 2222,
  "PublicPort": 3333,
  "Type": "tcp"
}

为了捕获这个,我有一个枚举和一个结构:

#[derive(Eq, PartialEq, Deserialize, Serialize, Debug)]
#[serde(rename_all = "snake_case")]
pub enum PortType {
    Sctp,
    Tcp,
    Udp,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct PortMapping {
    pub private_port: u16,
    pub public_port: u16,
    #[serde(rename = "Type")]
    pub port_type: PortType,
}

目前,此 API 仅支持 PortType 中列出的三种协议(protocol),但我们假设将来会添加对 DCCP 的支持。我不希望 API 的客户端仅仅因为他们可能没有查看的配置选项中的未知字符串而开始失败。

为了解决这个问题,我添加了一个 Unknown 变体和一个 String 来表示值:

#[derive(Eq, PartialEq, Deserialize, Serialize, Debug)]
#[serde(rename_all = "snake_case")]
pub enum PortType {
    Sctp,
    Tcp,
    Udp,
    Unknown(String),
}

这里的目标是在传入未知值时以稍微不方便的 PortType::Unknown("dccp") 值结束。当然,这不是我想要的就像开箱即用——传递未知的 "dccp" 值将导致:

Error("unknown variant `dccp`, expected one of `sctp`, `tcp`, `udp`, `unknown`", line: 1, column: 55)

是否有 Serde 配置可以满足我的需求,或者我应该为 PortType 手动编写 DeserializeSerialize 实现?

最佳答案

这有一个问题,虽然它已经开放了 3 年,但到目前为止还没有完全解决。 Serde #912 .

在发表这篇文章时,目前正在实现的(虽然未记录)是 #[serde(other)]。它只能应用于单位枚举字段,这限制了它的用处:

#[derive(Deserialize, PartialEq)]
#[serde(tag = "tag")]
enum Target {
   A(()),
   B(()),
   #[serde(other)]
   Others
}

fn main() {
    assert_eq!(Target::Others, from_str::<Target>(r#"{ "tag": "blablah" }"#).unwrap());
}

除此之外,在撰写本文时唯一的其他方法是编写您自己的Deserialize 实现。

关于rust - 我如何支持 Serde 枚举的未知值或其他值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57469527/

相关文章:

rust - 如何在二进制项目中使用 src 文件夹外部的模块,例如用于集成测试或基准测试?

serialization - 序列化未实现序列化的外部 crate 枚举的 vec

rust - 如何使用 serde 从 XML 属性反序列化数字?

rust - Rust tokio_postgres行到对象的映射失败,时间戳列为serde_postgres

json - serde 中的 rustc_serialize::Json 等价于什么?

closures - 从闭包填充集合时类型不匹配 "bound lifetime parameter"与 "concrete lifetime"

rust - 如何在 doctest 中使用自定义模块?

rust - 如何可变地从 &&mut Foo 借用引用?

types - 什么时候明确类型注释?

json - 如何使用 Rust 关键字属性名称解码 JSON 对象?