Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 16 additions & 20 deletions wp_serde_helper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use serde::{
de::{self, DeserializeOwned, Unexpected},
ser,
};
use serde_json::Value;
use std::{fmt, marker::PhantomData};

pub use wp_serde_date::wp_utc_date_format;
Expand Down Expand Up @@ -361,15 +360,6 @@ impl<'de> de::Visitor<'de> for DeserializeStringVecOrStringAsOptionVisitor {
}
}

pub fn ok_or_default<'a, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: Deserialize<'a> + Default,
D: Deserializer<'a>,
{
let v: Value = Deserialize::deserialize(deserializer)?;
Ok(T::deserialize(v).unwrap_or_default())
}

struct DeserializeEmptyVecOrNone<T>(PhantomData<T>);

impl<'de, T> de::Visitor<'de> for DeserializeEmptyVecOrNone<T>
Expand Down Expand Up @@ -543,20 +533,26 @@ mod tests {
assert_eq!(expected_result, option_string_vec_or_string.string);
}

#[derive(Debug, Deserialize)]
pub struct OptionStringOrBool {
#[serde(deserialize_with = "ok_or_default")]
pub value: Option<String>,
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub struct OptionStructOrEmptyArray {
#[serde(deserialize_with = "deserialize_empty_vec_or_none")]
pub value: Option<OptionStructOrEmptyArrayInner>,
}

#[derive(Debug, Deserialize, PartialEq, Eq)]
pub struct OptionStructOrEmptyArrayInner {
foo: String,
}

#[rstest]
#[case(r#"{"value": "foo"}"#, Some("foo".to_string()))]
#[case(r#"{"value": "false"}"#, Some("false".to_string()))]
#[case(r#"{"value": false}"#, None)]
#[case(r#"{"value": {"foo": "bar"}}"#, Some(OptionStructOrEmptyArrayInner { foo: "bar".to_string() }))]
#[case(r#"{"value": []}"#, None)]
fn test_ok_or_default(#[case] test_case: &str, #[case] expected_result: Option<String>) {
let option_string_or_bool: OptionStringOrBool =
fn test_deserialize_empty_vec_or_none(
#[case] test_case: &str,
#[case] expected_result: Option<OptionStructOrEmptyArrayInner>,
) {
let option_struct: OptionStructOrEmptyArray =
serde_json::from_str(test_case).expect("Test case should be a valid JSON");
assert_eq!(expected_result, option_string_or_bool.value);
assert_eq!(expected_result, option_struct.value);
}
}