我试图将JSON解析为一个包含chrono::DateTime个字段的 struct .JSON以自定义格式保存了时间戳,我为此编写了一个反序列化程序.

如何使用#[serde(deserialize_with)]连接这两者并使其工作?

我用NaiveDateTime表示更简单的代码

extern crate serde;
extern crate serde_json;
use serde::Deserialize;
extern crate chrono;
use chrono::NaiveDateTime;

fn from_timestamp(time: &String) -> NaiveDateTime {
    NaiveDateTime::parse_from_str(time, "%Y-%m-%dT%H:%M:%S.%f").unwrap()
}

#[derive(Deserialize, Debug)]
struct MyJson {
    name: String,
    #[serde(deserialize_with = "from_timestamp")]
    timestamp: NaiveDateTime,
}

fn main() {
    let result: MyJson =
        serde_json::from_str(r#"{"name": "asdf", "timestamp": "2019-08-15T17:41:18.106108"}"#)
            .unwrap();
    println!("{:?}", result);
}

我得到了三个不同的编译错误:

error[E0308]: mismatched types
  --> src/main.rs:11:10
   |
11 | #[derive(Deserialize, Debug)]
   |          ^^^^^^^^^^^ expected reference, found type parameter
   |
   = note: expected type `&std::string::String`
              found type `__D`

error[E0308]: mismatched types
  --> src/main.rs:11:10
   |
11 | #[derive(Deserialize, Debug)]
   |          ^^^^^^^^^^-
   |          |         |
   |          |         this match expression has type `chrono::NaiveDateTime`
   |          expected struct `chrono::NaiveDateTime`, found enum `std::result::Result`
   |          in this macro invocation
   |
   = note: expected type `chrono::NaiveDateTime`
              found type `std::result::Result<_, _>`

error[E0308]: mismatched types
  --> src/main.rs:11:10
   |
11 | #[derive(Deserialize, Debug)]
   |          ^^^^^^^^^^-
   |          |         |
   |          |         this match expression has type `chrono::NaiveDateTime`
   |          expected struct `chrono::NaiveDateTime`, found enum `std::result::Result`
   |          in this macro invocation
   |
   = note: expected type `chrono::NaiveDateTime`
              found type `std::result::Result<_, _>`

我很确定from_timestamp函数返回的是DateTime struct 而不是Result,所以我不知道"expected struct chrono::NaiveDateTime,found enum std::result::Result"是什么意思.

推荐答案

这相当复杂,但以下工作:

use chrono::NaiveDateTime;
use serde::de;
use serde::Deserialize;
use std::fmt;

struct NaiveDateTimeVisitor;

impl<'de> de::Visitor<'de> for NaiveDateTimeVisitor {
    type Value = NaiveDateTime;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "a string represents chrono::NaiveDateTime")
    }

    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        match NaiveDateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S.%f") {
            Ok(t) => Ok(t),
            Err(_) => Err(de::Error::invalid_value(de::Unexpected::Str(s), &self)),
        }
    }
}

fn from_timestamp<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
where
    D: de::Deserializer<'de>,
{
    d.deserialize_str(NaiveDateTimeVisitor)
}

#[derive(Deserialize, Debug)]
struct MyJson {
    name: String,
    #[serde(deserialize_with = "from_timestamp")]
    timestamp: NaiveDateTime,
}

fn main() {
    let result: MyJson =
        serde_json::from_str(r#"{"name": "asdf", "timestamp": "2019-08-15T17:41:18.106108"}"#)
            .unwrap();
    println!("{:?}", result);
}

Rust相关问答推荐

生成的future 的 struct 是什么?

如何处理对打包字段的引用是未对齐错误?

WebDriver等待三十四?(Rust Se)

使用InlineTables序列化toml ArrayOfTables

无法在线程之间安全地发送future (&Q;)&错误

如果A == B,则将Rc A下推到Rc B

有没有办法在Rust中配置常量变量的值?

如何go 除铁 rust 中路径组件的第一项和最后一项?

如何点击()迭代器?

如果变量本身不是None,如何返回;如果没有,则返回None&Quot;?

如何在Rust中缩短数组

如何获取光标下的像素 colored颜色 ?

使用 pyo3 将 Rust 转换为 Python 自定义类型

Rust 为什么被视为borrow ?

将 `&T` 转换为新类型 `&N`

有没有更好的方法来为拥有 DIsplay 事物集合的 struct 实现 Display?

Iterator::collect如何进行转换?

如何构建包含本地依赖项的 docker 镜像?

为什么 std::iter::Peekable::peek 可变地borrow self 参数?

如何将 while 循环内的用户输入添加到 Rust 中的向量?