FromStr based empty_string_as_none implementation (#486)

This commit is contained in:
Imbolc 2021-11-09 15:05:31 +03:00 committed by GitHub
parent 9c77ee0295
commit 2ee66e812f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -5,7 +5,8 @@
//! ```
use axum::{extract::Query, routing::get, Router};
use serde::{de::IntoDeserializer, Deserialize, Deserializer};
use serde::{de, Deserialize, Deserializer};
use std::{fmt, str::FromStr};
#[tokio::main]
async fn main() {
@ -34,7 +35,7 @@ async fn handler(Query(params): Query<Params>) -> String {
#[allow(dead_code)]
struct Params {
#[serde(default, deserialize_with = "empty_string_as_none")]
foo: Option<String>,
foo: Option<i32>,
bar: Option<String>,
}
@ -42,12 +43,13 @@ struct Params {
fn empty_string_as_none<'de, D, T>(de: D) -> Result<Option<T>, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de>,
T: FromStr,
T::Err: fmt::Display,
{
let opt = Option::<String>::deserialize(de)?;
match opt.as_deref() {
None | Some("") => Ok(None),
Some(s) => T::deserialize(s.into_deserializer()).map(Some),
Some(s) => FromStr::from_str(s).map_err(de::Error::custom).map(Some),
}
}
@ -60,8 +62,8 @@ mod tests {
#[tokio::test]
async fn test_something() {
assert_eq!(
send_request_get_body("foo=foo&bar=bar").await,
r#"Params { foo: Some("foo"), bar: Some("bar") }"#,
send_request_get_body("foo=1&bar=bar").await,
r#"Params { foo: Some(1), bar: Some("bar") }"#,
);
assert_eq!(
@ -75,8 +77,8 @@ mod tests {
);
assert_eq!(
send_request_get_body("foo=foo").await,
r#"Params { foo: Some("foo"), bar: None }"#,
send_request_get_body("foo=1").await,
r#"Params { foo: Some(1), bar: None }"#,
);
assert_eq!(