gpt4 book ai didi

rust - 是否有更简单的方法在反序列化时转换类型?

转载 作者:行者123 更新时间:2023-11-29 07:48:07 28 4
gpt4 key购买 nike

使用 serde_json ,我有带有 String 的 JSON 对象,我需要将其转换为 float 。我偶然发现了一个自定义反序列化器解决方案,但它看起来像是一个 hack。 Here is a working playground example of the code below.

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use serde_json::Error;
use serde::de::{Deserialize, DeserializeOwned, Deserializer};

#[derive(Serialize, Deserialize)]
struct Example {
#[serde(deserialize_with = "coercible")]
first: f64,
second: f64,
}

fn coercible<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: DeserializeOwned,
D: Deserializer<'de>,
{
use serde::de::Error;
let j = String::deserialize(deserializer)?;
serde_json::from_str(&j).map_err(Error::custom)
}

fn typed_example() -> Result<(), Error> {
let data = r#"["3.141",1.618]"#;
let e: Example = serde_json::from_str(data)?;
println!("{} {}", e.first * 2.0, e.second * 2.0);
Ok(())
}

fn main() {
typed_example().unwrap();
}

上面的代码如你所料编译和运行,输出两个 float 。

我正在尝试了解反序列化器解决方案的工作原理,但我想知道我是否正朝着正确的方向前进,或者是否有更好的方法来做到这一点。

最佳答案

使用 coercible 有点意外。有了它,输入 "3.141" 被剥离了它的 "",所以我将 3.141 送入 serde_json::from_str(&j),它适本地返回了一个 float 。例如,当输入 JSON 包含意外值时,这个意外的解决方案很容易出错且令人困惑。

我阅读了 Serde 文档(一个很好的学习练习)并想出了在反序列化 JSON ( working playground here ) 时将字符串转换为 f64 的适当方法:

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use std::fmt;
use serde_json::Error;
use serde::de::{self, Deserializer, Unexpected, Visitor};

#[derive(Serialize, Deserialize)]
struct Example {
#[serde(deserialize_with = "string_as_f64")]
first: f64,
second: f64,
}

fn string_as_f64<'de, D>(deserializer: D) -> Result<f64, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_f64(F64Visitor)
}

struct F64Visitor;
impl<'de> Visitor<'de> for F64Visitor {
type Value = f64;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string representation of a f64")
}
fn visit_str<E>(self, value: &str) -> Result<f64, E>
where
E: de::Error,
{
value.parse::<f64>().map_err(|_err| {
E::invalid_value(Unexpected::Str(value), &"a string representation of a f64")
})
}
}

fn typed_example() -> Result<(), Error> {
let data = r#"["3.141",1.618]"#;
let e: Example = serde_json::from_str(data)?;
println!("{} {}", e.first * 2.0, e.second * 2.0);
Ok(())
}

fn main() {
typed_example().unwrap();
}

感谢 Serde 开发人员,因为尽管 Serde documentation在我看来似乎完全迟钝,但事实证明它非常有帮助且易于理解。我只需要从头开始慢慢阅读。

关于rust - 是否有更简单的方法在反序列化时转换类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44836327/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com