在Rust中使用Serde从json中提升嵌套值可能是可选的

  • 本文关键字:嵌套 Rust Serde json rust serde
  • 更新时间 :
  • 英文 :


我使用的是这个解决方案:

在使用Serde反序列化对象时,有没有方法可以省略包装器/根对象?

从嵌套json结构中提取浮点值:

这是JSON

"activitiesWon": {
"statId": "activitiesWon",
"basic": {
"value": 3.0,
"displayValue": "3"
}
},

这里是数据结构和客户反序列化程序:

#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy)]
pub struct PvpStatsData {
#[serde(rename = "activitiesWon", deserialize_with="property_to_float")]
pub activities_won:f32,
}
pub fn property_to_float<'de, D>(deserializer: D) -> Result<f32, D::Error>
where D: serde::de::Deserializer<'de>,
{
#[derive(Deserialize)]
struct Outer {
pub basic: Inner,
}

#[derive(Deserialize)]
struct Inner {
pub value: f32,
}
let helper = Outer::deserialize(deserializer)?;
Ok(helper.basic.value)
}

这很管用。然而,有些结构/属性可能不存在,因此它们的字段签名看起来是这样的,使用自定义反序列化程序,它要么返回Option,要么返回None:

#[derive(Serialize, Deserialize, Debug, Default, Clone, Copy)]
pub struct PvpStatsData {
#[serde(rename = "bestSingleGameKills", deserialize_with="property_to_option_float")]
pub best_single_game_kills:Option<f32>,
}
pub fn property_to_option_float<'de, D>(deserializer: D) -> Result<Option<f32>, D::Error>
where D: serde::de::Deserializer<'de>,
{
println!("PARSER");
#[derive(Deserialize, Debug, )]
struct Outer {
pub basic: Inner,
}

#[derive(Deserialize, Debug, )]
struct Inner {
pub value: f32,
}
Option::<Outer>::deserialize(deserializer).map(|o:Option<Outer>| match o {
Some(e) => {
println!("{:?}", e);
Some(e.basic.value)
},
None => None,
})
}

然而,在解析时,如果json中不存在该属性,那么我会得到一个解析错误:

serde_json::Error : Error("missing field `bestSingleGameKills`", line: 1, column: 4358)

并且我的自定义反序列化方法从未被调用。

有人知道为什么不调用反序列化方法吗?和/或当该属性不存在时,我如何才能调用它?我有其他反序列化程序可以处理Optional结果,但我怀疑这与嵌套json和option的组合有关。

我在这里发布了一个例子的操场:https://play.rust-lang.org/?version=stable&mode=调试&edition=2018&gist=022d7ca3513e411644d186518d177645

(只需取消注释第二个json块即可查看问题(

default字段属性应该可以工作(我假设您可以接受bestrongingle_game_kills在json中不存在时默认为None(。

#[derive(Deserialize, Debug, Default, Clone, Copy)]
pub struct PvpStatsData {
#[serde(default, rename = "activitiesWon", deserialize_with="property_to_float")]
pub activities_won:f32,

#[serde(default, rename = "bestSingleGameKills", deserialize_with="property_to_option_float")]
pub best_single_game_kills:Option<f32>,
}

https://play.rust-lang.org/?version=stable&mode=调试&edition=2018&gist=a50748b2fb585a9430371a6ecd10f82

最新更新