Skip to content

Commit f756da1

Browse files
committed
Add a u64 parser
Handles cases like: - Valid u64 - `null` - -1 (used in some cases in place of `null`) - `false` (used in some cases in place of `null`)
1 parent cc9fa67 commit f756da1

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

wp_serde_helper/src/lib.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,58 @@ where
298298
deserializer.deserialize_any(DeserializeEmptyArrayOrHashMapVisitor::<K, V>(PhantomData))
299299
}
300300

301+
pub fn deserialize_u64_or_none<'de, D>(deserializer: D) -> Result<Option<u64>, D::Error>
302+
where
303+
D: Deserializer<'de>,
304+
{
305+
deserializer.deserialize_any(DeserializeU64OrNoneVisitor)
306+
}
307+
308+
pub struct DeserializeU64OrNoneVisitor;
309+
310+
impl de::Visitor<'_> for DeserializeU64OrNoneVisitor {
311+
type Value = Option<u64>;
312+
313+
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
314+
formatter.write_str("u64, -1, false, or null")
315+
}
316+
317+
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
318+
where
319+
E: de::Error,
320+
{
321+
Ok(Some(v))
322+
}
323+
324+
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
325+
where
326+
E: de::Error,
327+
{
328+
if v == -1 {
329+
return Ok(None);
330+
}
331+
332+
return Err(E::invalid_value(Unexpected::Signed(v), &self))
333+
}
334+
335+
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
336+
where
337+
E: de::Error, {
338+
if !v {
339+
return Ok(None);
340+
}
341+
342+
return Err(E::invalid_value(Unexpected::Bool(v), &self))
343+
}
344+
345+
fn visit_unit<E>(self) -> Result<Self::Value, E>
346+
where
347+
E: de::Error, {
348+
Ok(None)
349+
}
350+
}
351+
352+
301353
#[cfg(test)]
302354
mod tests {
303355
use super::*;
@@ -388,4 +440,20 @@ mod tests {
388440
serde_json::from_str(test_case).expect("Test case should be a valid JSON");
389441
assert_eq!(expected_result, wrapper.map);
390442
}
443+
444+
#[derive(Debug, Deserialize)]
445+
pub struct EmptyUIntOrEmpty {
446+
#[serde(deserialize_with = "deserialize_u64_or_empty")]
447+
pub value: Option<u64>,
448+
}
449+
450+
#[rstest]
451+
#[case(r#"{"value": 1}"#, Some(1))]
452+
#[case(r#"{"value": null}"#, None)]
453+
#[case(r#"{"value": -1}"#, None)]
454+
fn test_deserialize_empty_uint_or_empty(#[case] test_case: &str, #[case] expected_result: Option<u64>) {
455+
let empty_uint_or_empty: EmptyUIntOrEmpty = serde_json::from_str(test_case).expect("Test case should be a valid JSON");
456+
assert_eq!(expected_result, empty_uint_or_empty.value);
457+
}
458+
391459
}

0 commit comments

Comments
 (0)