如何解决如何使用Serde反序列化Prost枚举?
我正在使用[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,::prost::Enumeration)]
#[repr(i32)]
#[derive(serde_derive::Deserialize)]
#[serde(from = "&str")] // This line
pub enum Direction {
Up = 0,}
具有以下功能:
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 docs告诉了我,该方法甚至没有被调用(但编译成功)。
我还在Direction
字段上尝试了一个字段属性:
#[serde(deserialize_with = \"super::super::common::Direction::from\")]
但是那当然需要与&str
不同的签名:the trait std::convert::From<__D> is not implemented for common::Direction
我是否只需要编写自定义解串器?似乎是一个足够常见的用例,将有一种模式可以使用。
注意:这与serde_repr
解决的问题相反。我没有办法在这里使用它。
解决方法
由于this answer中的指南,我实现了自己的解串器。可能有一种更简单或更惯用的方法,因此,如果您知道一个,请分享!
Serde属性,在字段而不是Enum上设置:
config.field_attribute(
"direction","#[serde(deserialize_with = \"super::super::common::Direction::from_str\")]"
);
反序列化器:
impl Direction {
pub fn from_str<'de,D>(deserializer: D) -> Result<i32,D::Error>
where D: Deserializer<'de>
{
let s: &str = Deserialize::deserialize(deserializer)?;
match s.to_lowercase().as_str() {
"up" => Ok(Self::Tx as i32),"down" => Ok(Self::Down as i32),"sideways" => Ok(Self::Sideways as i32),_ => Err(de::Error::unknown_variant(s,&["up","down","sideways"]))
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。