我正在使用 [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"
转换为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
的签名: trait std::convert::From<__D>未为common::Direction实现
我是否只需编写自定义反序列化器?看起来这是很常见的用例,应该有一种可用的模式。
注意:这与serde_repr
解决的问题相反。我没有看到在这里使用它的方法。