gpt4 book ai didi

json - 如何编写 Serde Visitor 将字符串数组转换为 Vec>?

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

我需要将 JSON 反序列化为具有 Vec<Vec<f64>> 的结构 field 。 JSON 有数字字符串,所以我需要一个自定义反序列化器将字符串转换为 f64在反序列化期间。

我想反序列化的示例 JSON:

{
"values": [["2", "1.4"], ["8.32", "1.5"]]
}

我的结构是这样的:

#[derive(Deserialize)]
struct Payload {
#[serde(default, deserialize_with = "from_array_of_arrays_of_strs")]
values: Vec<Vec<f64>>,
}

我看到你可能会对访问者这样做 in the examples of Serde ,所以我实现了这个访问者:

fn from_array_of_arrays_of_strs<'de, T, D>(deserializer: D) -> Result<Vec<Vec<f64>>, D::Error>
where
T: Deserialize<'de>,
D: Deserializer<'de>,
{
struct F64Visitor(PhantomData<fn() -> Vec<Vec<f64>>>);

impl<'de> Visitor<'de> for F64Visitor {
type Value = Vec<Vec<f64>>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a nonempty sequence of numbers")
}

#[inline]
fn visit_str<E>(self, value: &str) -> Result<f64, E>
where
E: serde::de::Error,
{
self.visit_string(String::from(value))
}

#[inline]
fn visit_string<E>(self, value: String) -> Result<f64, E> {
Ok(value.parse::<f64>().unwrap())
}

#[inline]
fn visit_seq<V, T>(self, mut visitor: V) -> Result<Vec<T>, V::Error>
where
V: SeqAccess<'de>,
{
let mut vec = Vec::new();

while let Some(elem) = try!(visitor.next_element()) {
vec.push(elem);
}

Ok(vec)
}
}

let visitor = F64Visitor(PhantomData);
deserializer.deserialize_seq(visitor)
}

playground

编译器提示 visit_strvisit_string具有不兼容的特征类型:

error[E0053]: method `visit_str` has an incompatible type for trait
--> src/main.rs:32:9
|
32 | / fn visit_str<E>(self, value: &str) -> Result<f64, E>
33 | | where
34 | | E: serde::de::Error,
35 | | {
36 | | self.visit_string(String::from(value))
37 | | }
| |_________^ expected struct `std::vec::Vec`, found f64
|
= note: expected type `fn(from_array_of_arrays_of_strs::F64Visitor, &str) -> std::result::Result<std::vec::Vec<std::vec::Vec<f64>>, E>`
found type `fn(from_array_of_arrays_of_strs::F64Visitor, &str) -> std::result::Result<f64, E>`

error[E0053]: method `visit_string` has an incompatible type for trait
--> src/main.rs:40:9
|
40 | / fn visit_string<E>(self, value: String) -> Result<f64, E> {
41 | | Ok(value.parse::<f64>().unwrap())
42 | | }
| |_________^ expected struct `std::vec::Vec`, found f64
|
= note: expected type `fn(from_array_of_arrays_of_strs::F64Visitor, std::string::String) -> std::result::Result<std::vec::Vec<std::vec::Vec<f64>>, E>`
found type `fn(from_array_of_arrays_of_strs::F64Visitor, std::string::String) -> std::result::Result<f64, E>`

error[E0049]: method `visit_seq` has 2 type parameters but its trait declaration has 1 type parameter
--> src/main.rs:45:21
|
45 | fn visit_seq<V, T>(self, mut visitor: V) -> Result<Vec<T>, V::Error>
| ^^^^^^ found 2 type parameters, expected 1

我想我对访问者的工作方式没有正确的理解。我可以只有一个访问者来反序列化字符串数组,还是我需要一个访问者来反序列化数组和一个访问者来将字符串反序列化为 f64

我读过:

最佳答案

How to transform fields before deserialization using serde? 中所述,最简单的解决方案是为您的字符串作为浮点值引入一个新类型。然后你可以实现 Deserialize为此,利用 Deserialize 的现有实现和字符串解析:

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

use serde::de::{Deserialize, Deserializer, Error, Unexpected};

#[derive(Debug, Deserialize)]
struct Payload {
#[serde(default)]
values: Vec<Vec<Value>>,
}

#[derive(Debug)]
struct Value(f64);

impl<'de> Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
where D: Deserializer<'de>
{
let s: &str = Deserialize::deserialize(deserializer)?;
s.parse()
.map(Value)
.map_err(|_| D::Error::invalid_value(Unexpected::Str(s), &"a floating point number as a string"))
}
}

fn main() {
let input = r#"
{
"values": [["2", "1.4"], ["8.32", "1.5"]]
}
"#;

let out: Payload = serde_json::from_str(input).unwrap();

println!("{:?}", out);
}

我更喜欢这种解决方案,因为在很多情况下我希望这种新类型在我的系统中发挥作用。


如果你真的,真的需要反序列化一次并且正好是一个 Vec<Vec<f64>> ,您必须实现两个访问者。一个将反序列化外部 Vec , 一个将反序列化内部 Vec .我们将重复使用之前的 Value newtype,但内部访问者会将其剥离。外部访问者将对内部访问者周围的新类型做同样的事情:

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

use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Unexpected, Visitor};
use std::fmt;

#[derive(Debug, Deserialize)]
struct Payload {
#[serde(default, deserialize_with = "from_array_of_arrays_of_strs")]
values: Vec<Vec<f64>>,
}

fn from_array_of_arrays_of_strs<'de, D>(deserializer: D) -> Result<Vec<Vec<f64>>, D::Error>
where
D: Deserializer<'de>,
{
struct OuterVisitor;

impl<'de> Visitor<'de> for OuterVisitor {
type Value = Vec<Vec<f64>>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a nonempty sequence of a sequence of numbers")
}

#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: SeqAccess<'de>,
{
let mut vec = Vec::new();

while let Some(Inner(elem)) = try!(visitor.next_element()) {
vec.push(elem);
}

Ok(vec)
}
}

deserializer.deserialize_seq(OuterVisitor)
}

struct Inner(Vec<f64>);

impl<'de> Deserialize<'de> for Inner {
fn deserialize<D>(deserializer: D) -> Result<Inner, D::Error>
where
D: Deserializer<'de>,
{
struct InnerVisitor;

impl<'de> Visitor<'de> for InnerVisitor {
type Value = Inner;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a nonempty sequence of numbers")
}

#[inline]
fn visit_seq<V>(self, mut visitor: V) -> Result<Inner, V::Error>
where
V: SeqAccess<'de>,
{
let mut vec = Vec::new();

while let Some(Value(elem)) = try!(visitor.next_element()) {
vec.push(elem);
}

Ok(Inner(vec))
}
}

deserializer.deserialize_seq(InnerVisitor)
}
}

struct Value(f64);

impl<'de> Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(deserializer)?;
s.parse().map(Value).map_err(|_| {
D::Error::invalid_value(Unexpected::Str(s), &"a floating point number as a string")
})
}
}

fn main() {
let input = r#"
{
"values": [["2", "1.4"], ["8.32", "1.5"]]
}
"#;

let out: Payload = serde_json::from_str(input).unwrap();

println!("{:?}", out);
}

关于json - 如何编写 Serde Visitor 将字符串数组转换为 Vec<Vec<f64>>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48288988/

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