我正在使用 [prost] 从 protobuf 生成结构。其中一个结构非常简单:
enum Direction {
up = 0;
down = 1;
sideways = 2;
}
这会生成如下代码:
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
#[derive(serde_derive::Deserialize)]
pub enum Direction {
Up = 0,
Down = 1,
Sideways = 2,
}
我必须将大量 JSON 文件解析为这些消息。这些是数万行长,但是当这个字段出现时,它看起来像:
{ "direction": "up" }
所以,简而言之,它的反序列化格式是一个字符串,序列化是i32
.
如果我只是运行它并尝试解析 JSON,我会得到:
thread 'tests::parse_json' panicked at 'Failed to parse: "data/my_data.json": Error("invalid type: string \"up\", expected i32", line: 132, column: 23)
这当然是有道理的——没有反射来引导反序列化从"up"
to 0
。
问题:如何设置serde
将这些字符串解析为匹配的整数值?我已经彻底阅读了 serde 文档,看来我可能需要为此编写一个自定义反序列化器,尽管这似乎有点过头了。
我尝试了一些不同的 serde 属性,例如:
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
#[derive(serde_derive::Deserialize)]
#[serde(from = "&str")] // This line
pub enum Direction {
Up = 0,
Down = 1,
Sideways = 2,
}
使用此功能:
impl From<&str> for Direction {
fn from(item: &str) -> Self {
match item {
"up" => Self::Up,
"down" => Self::Down,
"sideways" => Self::Sideways,
_ => panic!("Invalid value for Direction: {}", item),
}
}
}
但是,尽管serde 文档告诉我,该方法甚至没有被调用(但编译成功)。
我还在字段上尝试了一个字段属性Direction
:
#[serde(deserialize_with = \"super::super::common::Direction::from\")]
但这当然需要一个不同的签名,而不仅仅是&str
:the trait std::convert::From<__D> is not implemented for common::Direction
我只需要编写一个自定义反序列化器吗?似乎是一个足够常见的用例,可以使用一种模式。
注意:这是解决的相反问题serde_repr
。我没有看到让它在这里工作的方法。