From 9edf46b697ed1f7ee1f5ef66dfa75a0a138f3f89 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Wed, 14 Oct 2026 20:29:39 -0700 Subject: [PATCH] Validate the selected union member with serdevalid Signed-off-by: Eric Liu --- src/one_any_of.rs | 12 ++++++++++- tests/union_validation.rs | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 tests/union_validation.rs diff --git a/src/one_any_of.rs b/src/one_any_of.rs index f3dcaa606..58b034c92 100644 --- a/src/one_any_of.rs +++ b/src/one_any_of.rs @@ -20,7 +20,6 @@ macro_rules! common_one_any_of { ) => { #[doc = concat!("`", stringify!($t), "` type.\n\nThis allows modelling of ", stringify!($schema), " JSON schemas.")] #[cfg_attr(feature = "conversion", derive(LabelledGenericEnum))] - #[cfg_attr(feature = "serdevalid", derive(Validate))] #[derive(Debug, PartialEq, Clone)] pub enum $t<$($i),*> where $($i: PartialEq,)* @@ -31,6 +30,17 @@ macro_rules! common_one_any_of { ),* } + #[cfg(feature = "serdevalid")] + impl<$($i),*> Validate for $t<$($i),*> where + $($i: PartialEq + Validate,)* + { + fn validate(&self) -> Result<(), serde_valid::validation::Errors> { + match self { + $(Self::$i(inner) => inner.validate()),* + } + } + } + impl<$($i),*> Serialize for $t<$($i),*> where $($i: PartialEq + Serialize,)* { diff --git a/tests/union_validation.rs b/tests/union_validation.rs new file mode 100644 index 000000000..f3d26104b --- /dev/null +++ b/tests/union_validation.rs @@ -0,0 +1,42 @@ +#![cfg(feature = "serdevalid")] + +use serde_valid::Validate; +use swagger::{AnyOf2, OneOf2}; + +#[derive(Debug, PartialEq, Validate)] +struct Positive { + #[validate(minimum = 1)] + value: i32, +} + +#[test] +fn oneof_validates_the_selected_member() { + for value in [0, 1] { + for union in [ + OneOf2::::A(Positive { value }), + OneOf2::B(Positive { value }), + ] { + assert_eq!(union.validate().is_ok(), value == 1); + } + } +} + +#[test] +fn anyof_validates_the_selected_member() { + for value in [0, 1] { + for union in [ + AnyOf2::::A(Positive { value }), + AnyOf2::B(Positive { value }), + ] { + assert_eq!(union.validate().is_ok(), value == 1); + } + } +} + +#[test] +fn unions_with_primitive_members_still_serialize_and_deserialize() { + let oneof: OneOf2 = serde_json::from_str("\"future\"").unwrap(); + assert_eq!(serde_json::to_string(&oneof).unwrap(), "\"future\""); + let anyof: AnyOf2 = serde_json::from_str("42").unwrap(); + assert_eq!(serde_json::to_string(&anyof).unwrap(), "42"); +}