gpt4 book ai didi

serialization - 使用#[serde(untagged)] 和#[serde(with)] 的组合反序列化枚举

转载 作者:行者123 更新时间:2023-12-05 04:47:54 36 4
gpt4 key购买 nike

我正在尝试使用 actix-web 服务器作为通往小型堆栈的网关,以保证堆栈内部的数据格式严格,同时为用户提供一些自由。

为此,我想将 JSON 字符串反序列化为结构,然后对其进行验证、再次序列化并将其发布到消息代理上。数据的主要部分是包含整数、 float 和日期时间的数组数组。我使用 serde 进行反序列化,使用 chrono 来处理日期时间。

我尝试使用结构和枚举来允许不同的类型:

#[derive(Serialize, Deserialize)]
pub struct Data {
pub column_names: Option<Vec<String>>,
pub values: Vec<Vec<ValueType>>,
}

#[derive(Serialize, Deserialize)]
#[serde(untagged)]
pub enum ValueType {
I32(i32),
F64(f64),
#[serde(with = "datetime_handler")]
Dt(DateTime<Utc>),
}

chrono::DateTime<T>不执行Serialize ,我为此添加了一个自定义模块,类似于它的描述 in the serde docs .

mod datetime_handler {
use chrono::{DateTime, TimeZone, Utc};
use serde::{self, Deserialize, Deserializer, Serializer};

pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = dt.to_rfc3339();
serializer.serialize_str(&s)
}

pub fn deserialize<'de, D>(deserializer: D) -> Result<DateTime<Utc>, D::Error>
where
D: Deserializer<'de>,
{
println!("Checkpoint 1");
let s = String::deserialize(deserializer)?;
println!("{}", s);
println!("Checkpoint 2");
let err1 = match DateTime::parse_from_rfc3339(&s) {
Ok(dt) => return Ok(dt.with_timezone(&Utc)),
Err(e) => Err(e),
};
println!("Checkpoint 3");

const FORMAT1: &'static str = "%Y-%m-%d %H:%M:%S";
match Utc.datetime_from_str(&s, FORMAT1) {
Ok(dt) => return Ok(dt.with_timezone(&Utc)),
Err(e) => println!("{}", e), // return first error not second if both fail
};
println!("Checkpoint 4");

return err1.map_err(serde::de::Error::custom);
}
}

这会依次尝试 2 种不同的时间格式,并且适用于 DateTime 字符串。

问题

`#[derive(Serialize, Deserialize)]`、`#[serde(untagged)]` 和 `#[serde(with)]` 的组合似乎做了一些意想不到的事情。 `serde:from_str(...)` 尝试使用我自定义的 `deserialize` 函数反序列化数组中的每个条目。我希望它首先尝试反序列化为“ValueType::I32”,成功并继续下一个条目,如 [文档](https://serde.rs/enum-representations.html) 所说:

Serde will try to match the data against each variant in order and the first one that deserializes successfully is the one returned.

发生的是自定义 deserialize适用于例如"0"失败,反序列化停止。

这是怎么回事?我该如何解决?

我的想法是,我要么未能以错误的方式反序列化,要么我以某种方式“覆盖”了派生的反序列化。

最佳答案

@jonasbb 帮助我意识到代码在使用 [0,16.9,"2020-12-23 00:23:14"] 时有效,但在尝试反序列化 [ “0”,“16.9”,“2020-12-23 00:23:14”]。默认情况下,Serde 不会序列化字符串中的数字,对 I32 和 F64 的尝试只会默默地失败。这在本 serde-issue 中讨论可以使用非官方 serde-aux 解决 crate 。

关于serialization - 使用#[serde(untagged)] 和#[serde(with)] 的组合反序列化枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68314646/

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