我正在尝试使用actix-web服务器作为小型堆栈的网关,以保证堆栈内部的严格数据格式,同时为用户提供一些自由。
为此,我想将 JSON 字符串反序列化到结构中,然后对其进行验证,再次序列化它并将其发布在消息代理上。数据的主要部分是一个数组,其中包含整数,浮点数和日期时间。我使用 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>),
}
由于<code>chrono::DateTime
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);
}
}
这将一个接一个地尝试两种不同的时间格式,并适用于日期时间字符串。
Serde 将尝试按顺序将数据与每个变体进行匹配,第一个成功反序列化的数据是返回的变体。
发生的情况是自定义的< code >反序列化应用于例如< code >“0”失败,反序列化停止。
这是怎么回事?我怎么解决?
我的想法是,我要么以错误的方式反序列化失败,要么以某种方式用我自己的方式“覆盖”了派生的反序列化。
许多板条箱将实现< code>serde和其他常见的实用板条箱,但将它们作为可选功能。这有助于编译时节省时间。您可以通过查看Cargo.toml文件来检查一个板条箱,以查看是否有该板条箱的某个功能,或者是否包含了依赖项但标记为可选。
对于您的情况,我可以访问crates.io上的< code>chrono,并选择存储库链接来查看crates的源代码。在< code>Cargo.toml文件中,我可以看到使用了serde,但是默认情况下没有启用。
[features]
default = ["clock", "std", "oldtime"]
alloc = []
std = []
clock = ["libc", "std", "winapi"]
oldtime = ["time"]
wasmbind = ["wasm-bindgen", "js-sys"]
unstable-locales = ["pure-rust-locales", "alloc"]
__internal_bench = []
__doctest = []
[depenencies]
...
serde = { version = "1.0.99", default-features = false, optional = true }
要启用它,您可以进入货物。toml
,并将其作为功能添加到<code>chrono。
[depenencies]
chrono = { version: "0.4.19", features = ["serde"] }
或者,chrono
在其文档中列出了一些(但不是全部?)可选功能。但是,并非所有板条箱都这样做,文档有时可能会过时,因此我通常更喜欢手动方法。
至于deserialize_with
交互和枚举上未标记
之间的问题,我没有看到你的代码有任何问题。这可能是 serde 中的一个错误,所以我建议您在 serde 存储库上创建一个问题,以便他们可以进一步研究发生此错误的原因。
@jonasbb帮助我意识到使用< code>[0,16.9," 2020-12-23 00:23:14"]时代码可以工作,但在尝试反序列化< code>["0 "," 16.9 "," 2020-12-23 00:23:14"]时却不行。默认情况下,Serde不序列化字符串中的数字,对I32和F64的尝试只是无声地失败。这将在本期serde-aux中讨论,可以使用非正式serde-aux机箱解决。
问题内容: 我有一些从Web服务返回的JSON数据。JSON是顶级数组: 使用make 可以对数组中包含的数据进行反序列化,但是,我无法让Serde对顶级数组进行反序列化。 我是否缺少某些内容,还是Serde不能对顶级数组进行反序列化? 问题答案: 您可以使用:
问题内容: 我想使用自定义功能对a进行序列化和反序列化,但是Serde的书没有涵盖此功能,并且代码文档也无济于事。 我知道Serde可以很容易地反序列化,因为Chrono支持Serde, 但是 我想学习Serde,所以我想自己实现。当我运行此代码时,出现错误: 问题答案: 结构反序列化的默认行为是,当字段不以序列化形式出现时,为其分配各自的默认值。请注意,这与container 属性 不同,con
问题内容: 我如何使用gson 2.2.4序列化和反序列化一个简单的枚举? 问题答案: 根据 GsonAPI文档 ,Gson提供了的默认序列化/反序列化,因此基本上,应使用标准和方法(与其他类型一样)对序列化和反序列化。
我正在尝试使用Spring Cloud Stream框架构建一个简单的Kafka Streams应用程序。我可以连接到流以推送原始数据进行处理。但是当我尝试按键处理流进行事件计数时,我得到了未找到的运行应用程序时异常。我检查了我的项目包含的库,我可以找到类,它没有丢失。我不确定为什么在运行时它没有被加载! 下面是我的源文件。 <代码>com。pgp。学Kafka。分析。分析应用程序 <代码>com
我想序列化/反序列化具有可变行长度和内容的CSV文件,如下所示: /test.csv 在我看来,最简单的表示方法是下面的< code>enum: Cargo.toml 运行以下命令 梅因 指纹 使用和,是否有简单的解决方案?我觉得我遗漏了一两个<code>serde</code>属性,但在文档中还没有找到正确的属性。 编辑 Netwave建议添加属性。序列化现在可以工作了,反序列化会出现以下错误:
问题内容: 我正在使用JAVA 1.6和Jackson 1.9.9我有一个枚举 我添加了一个@JsonValue,这似乎可以将对象序列化为: 但是当我尝试反序列化时,我得到了 我在这里想念什么? 问题答案: 如果你希望将枚举类与其JSON表示完全脱钩,则@xbakesx指出的序列化器/反序列化器解决方案是一个很好的解决方案。 另外,如果你喜欢一个独立的解决方案,则基于·和·注释的实现会更方便。 因