如何使用Serde使用自定义函数反序列化可选字段?

我想chrono::NaiveDate使用自定义功能对a进行序列化和反序列化,但是Serde的书没有涵盖此功能,并且代码文档也无济于事。

#[macro_use]

extern crate serde_derive;

extern crate serde;

extern crate serde_json;

extern crate chrono;

use chrono::NaiveDate;

mod date_serde {

use chrono::NaiveDate;

use serde::{self, Deserialize, Serializer, Deserializer};

pub fn serialize<S>(date: &Option<NaiveDate>, s: S) -> Result<S::Ok, S::Error>

where S: Serializer {

if let Some(ref d) = *date {

return s.serialize_str(&d.format("%Y-%m-%d").to_string())

}

s.serialize_none()

}

pub fn deserialize<'de, D>(deserializer: D)

-> Result<Option<NaiveDate>, D::Error>

where D: Deserializer<'de> {

let s: Option<String> = Option::deserialize(deserializer)?;

if let Some(s) = s {

return Ok(Some(NaiveDate::parse_from_str(&s, "%Y-%m-%d").map_err(serde::de::Error::custom)?))

}

Ok(None)

}

}

#[derive(Debug, Serialize, Deserialize)]

struct Test {

pub i: u64,

#[serde(with = "date_serde")]

pub date: Option<NaiveDate>,

}

fn main() {

let mut test: Test = serde_json::from_str(r#"{"i": 3, "date": "2015-02-03"}"#).unwrap();

assert_eq!(test.i, 3);

assert_eq!(test.date, Some(NaiveDate::from_ymd(2015, 02, 03)));

test = serde_json::from_str(r#"{"i": 5}"#).unwrap();

assert_eq!(test.i, 5);

assert_eq!(test.date, None);

}

我知道Option<chrono::NaiveDate>Serde可以很容易地反序列化,因为Chrono支持Serde,

我想学习Serde,所以我想自己实现。当我运行此代码时,出现错误:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ErrorImpl { code: Message("missing field `date`"), line: 1, column: 8 }', /checkout/src/libcore/result.rs:859

note: Run with `RUST_BACKTRACE=1` for a backtrace.

回答:

结构反序列化的默认行为是,当字段不以序列化形式出现时,为其分配各自的默认值。请注意,这与container

#[serde(default)]属性不同,container 属性用结构的默认值填充字段。

#[derive(Debug, PartialEq, Deserialize)]

pub struct Foo<'a> {

x: Option<&'a str>,

}

let foo: Foo = serde_json::from_str("{}")?;

assert_eq!(foo, Foo { x: None });

但是,当我们使用另一个反序列化函数(#[serde(deserialize_with =

"path")])时,此规则会更改。Option这里的类型字段不再告诉反序列化器该字段可能不存在。相反,它表明存在一个字段,其内容可能为空或空(none以Serde术语)。在serde_json,例如,Option<String>是JavaScript相当于“任一nullstring”(null

| string在打字稿/流量表示)。下面的代码与给定的定义和日期反序列化器可以正常工作:

let test: Test = serde_json::from_str(r#"{"i": 5, "date": null}"#)?;

assert_eq!(test.i, 5);

assert_eq!(test.date, None);

幸运的是,仅通过添加serde(default)属性(Option::defaultyields None),反序列化过程就可以变得更加宽松:

#[derive(Debug, Serialize, Deserialize)]

struct Test {

pub i: u64,

#[serde(default)]

#[serde(with = "date_serde")]

pub date: Option<NaiveDate>,

}

操场

以上是 如何使用Serde使用自定义函数反序列化可选字段? 的全部内容, 来源链接: utcz.com/qa/422812.html

回到顶部