From 0554ae7cb8f0ab844826af6a6168374b5f529532 Mon Sep 17 00:00:00 2001 From: David Steele Date: Mon, 19 Jan 2026 17:32:39 +0000 Subject: [PATCH] fix: Fix rust-server model generation following serde_valid upgrade --- .../resources/rust-server/models.mustache | 18 +++++-- .../output/multipart-v3/src/models.rs | 1 - .../output/openapi-v3/src/models.rs | 10 ++-- .../src/models.rs | 53 +++++++++++++------ .../output/rust-server-test/src/models.rs | 21 +++++++- 5 files changed, 75 insertions(+), 28 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/rust-server/models.mustache b/modules/openapi-generator/src/main/resources/rust-server/models.mustache index b2e9fb779074..62cb60f97ed3 100644 --- a/modules/openapi-generator/src/main/resources/rust-server/models.mustache +++ b/modules/openapi-generator/src/main/resources/rust-server/models.mustache @@ -106,6 +106,17 @@ impl std::ops::DerefMut for {{{classname}}} { } } +{{^hasConflictingModelNames}} +#[cfg(feature = "validate")] +impl serde_valid::validation::ValidateCompositedMinLength for {{{classname}}} { + fn validate_composited_min_length( + &self, + _min_length: usize, + ) -> Result<(), serde_valid::validation::Composited> { + Ok(()) + } +} +{{/hasConflictingModelNames}} {{#exts.x-to-string-support}} {{#exts.x-is-string}} impl std::fmt::Display for {{{classname}}} { @@ -364,13 +375,13 @@ pub struct {{{classname}}} { )] {{/hasConflictingModelNames}} {{/hasValidation}} +{{#required}} {{^hasConflictingModelNames}}{{>validate}}{{/hasConflictingModelNames}} {{^hasConflictingModelNames}} {{#exts.x-needs-nested-validation}} - #[cfg_attr(feature = "validate", validate)] + {{^minLength}}{{^maxLength}}{{^minItems}}{{^maxItems}}#[cfg_attr(feature = "validate", validate)]{{/maxItems}}{{/minItems}}{{/maxLength}}{{/minLength}} {{/exts.x-needs-nested-validation}} {{/hasConflictingModelNames}} -{{#required}} pub {{{name}}}: {{{dataType}}}, {{/required}} {{^required}} @@ -378,9 +389,10 @@ pub struct {{{classname}}} { #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] #[serde(default = "swagger::nullable_format::default_optional_nullable")] {{/isNullable}} +{{^hasConflictingModelNames}}{{>validate}}{{/hasConflictingModelNames}} {{^hasConflictingModelNames}} {{#exts.x-needs-nested-validation}} - #[cfg_attr(feature = "validate", validate)] + {{^minLength}}{{^maxLength}}{{^minItems}}{{^maxItems}}#[cfg_attr(feature = "validate", validate)]{{/maxItems}}{{/minItems}}{{/maxLength}}{{/minLength}} {{/exts.x-needs-nested-validation}} {{/hasConflictingModelNames}} #[serde(skip_serializing_if="Option::is_none")] diff --git a/samples/server/petstore/rust-server/output/multipart-v3/src/models.rs b/samples/server/petstore/rust-server/output/multipart-v3/src/models.rs index 146e30a60279..b86871d13aec 100644 --- a/samples/server/petstore/rust-server/output/multipart-v3/src/models.rs +++ b/samples/server/petstore/rust-server/output/multipart-v3/src/models.rs @@ -13,7 +13,6 @@ use serde_valid::Validate; pub struct MultipartRelatedRequest { #[serde(rename = "object_field")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub object_field: Option, diff --git a/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs b/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs index c060d174617e..64d8c80a8d4c 100644 --- a/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs +++ b/samples/server/petstore/rust-server/output/openapi-v3/src/models.rs @@ -290,9 +290,9 @@ impl AdditionalPropertiesWithList { #[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] pub struct AdditionalPropertiesWithNullable { #[serde(rename = "nullableString")] - #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] #[serde(default = "swagger::nullable_format::default_optional_nullable")] + #[serde(skip_serializing_if="Option::is_none")] pub nullable_string: Option>, @@ -3446,30 +3446,30 @@ pub struct NullableTest { pub nullable: swagger::Nullable, #[serde(rename = "nullableWithNullDefault")] - #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] #[serde(default = "swagger::nullable_format::default_optional_nullable")] + #[serde(skip_serializing_if="Option::is_none")] pub nullable_with_null_default: Option>, #[serde(rename = "nullableWithPresentDefault")] - #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] #[serde(default = "swagger::nullable_format::default_optional_nullable")] + #[serde(skip_serializing_if="Option::is_none")] pub nullable_with_present_default: Option>, #[serde(rename = "nullableWithNoDefault")] - #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] #[serde(default = "swagger::nullable_format::default_optional_nullable")] + #[serde(skip_serializing_if="Option::is_none")] pub nullable_with_no_default: Option>, #[serde(rename = "nullableArray")] - #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] #[serde(default = "swagger::nullable_format::default_optional_nullable")] + #[serde(skip_serializing_if="Option::is_none")] pub nullable_array: Option>>, diff --git a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs index 947ba530d0d7..aa2800e329d3 100644 --- a/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs +++ b/samples/server/petstore/rust-server/output/petstore-with-fake-endpoints-models-for-testing/src/models.rs @@ -1096,14 +1096,12 @@ pub struct ArrayTest { #[serde(rename = "array_array_of_model")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub array_array_of_model: Option>>, #[serde(rename = "array_of_enum")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub array_of_enum: Option>, @@ -2641,21 +2639,18 @@ impl DollarSpecialLeftSquareBracketModelNameRightSquareBracket { pub struct EnumArrays { #[serde(rename = "just_symbol")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub just_symbol: Option, #[serde(rename = "array_enum")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub array_enum: Option>, #[serde(rename = "array_array_enum")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub array_array_enum: Option>>, @@ -3329,7 +3324,6 @@ impl EnumClass { pub struct EnumTest { #[serde(rename = "enum_string")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub enum_string: Option, @@ -3341,21 +3335,18 @@ pub struct EnumTest { #[serde(rename = "enum_integer")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub enum_integer: Option, #[serde(rename = "enum_number")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub enum_number: Option, #[serde(rename = "outerEnum")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub outer_enum: Option, @@ -4663,14 +4654,12 @@ pub struct MapTest { #[serde(rename = "map_map_of_enum")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub map_map_of_enum: Option>>, #[serde(rename = "map_of_enum_string")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub map_of_enum_string: Option>, @@ -4980,7 +4969,6 @@ pub struct MixedPropertiesAndAdditionalPropertiesClass { #[serde(rename = "map")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub map: Option>, @@ -5735,7 +5723,6 @@ impl NumberOnly { pub struct ObjectContainingObjectWithOnlyAdditionalProperties { #[serde(rename = "inner")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub inner: Option, @@ -5930,6 +5917,15 @@ impl std::ops::DerefMut for ObjectWithOnlyAdditionalProperties { } } +#[cfg(feature = "validate")] +impl serde_valid::validation::ValidateCompositedMinLength for ObjectWithOnlyAdditionalProperties { + fn validate_composited_min_length( + &self, + _min_length: usize, + ) -> Result<(), serde_valid::validation::Composited> { + Ok(()) + } +} /// Converts the ObjectWithOnlyAdditionalProperties value to the Query Parameters representation (style=form, explode=false) /// specified in /// Should be implemented in a serde serializer @@ -6064,7 +6060,6 @@ pub struct Order { #[serde(rename = "status")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub status: Option, @@ -6442,6 +6437,15 @@ impl std::ops::DerefMut for OuterBoolean { } } +#[cfg(feature = "validate")] +impl serde_valid::validation::ValidateCompositedMinLength for OuterBoolean { + fn validate_composited_min_length( + &self, + _min_length: usize, + ) -> Result<(), serde_valid::validation::Composited> { + Ok(()) + } +} /// Converts the OuterBoolean value to the Query Parameters representation (style=form, explode=false) /// specified in /// Should be implemented in a serde serializer @@ -6914,6 +6918,15 @@ impl std::ops::DerefMut for OuterNumber { } } +#[cfg(feature = "validate")] +impl serde_valid::validation::ValidateCompositedMinLength for OuterNumber { + fn validate_composited_min_length( + &self, + _min_length: usize, + ) -> Result<(), serde_valid::validation::Composited> { + Ok(()) + } +} /// Converts the OuterNumber value to the Query Parameters representation (style=form, explode=false) /// specified in /// Should be implemented in a serde serializer @@ -7056,6 +7069,15 @@ impl std::ops::DerefMut for OuterString { } } +#[cfg(feature = "validate")] +impl serde_valid::validation::ValidateCompositedMinLength for OuterString { + fn validate_composited_min_length( + &self, + _min_length: usize, + ) -> Result<(), serde_valid::validation::Composited> { + Ok(()) + } +} impl std::fmt::Display for OuterString { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0.clone()) @@ -7167,7 +7189,6 @@ pub struct Pet { #[serde(rename = "category")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub category: Option, @@ -7182,14 +7203,12 @@ pub struct Pet { #[serde(rename = "tags")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub tags: Option>, #[serde(rename = "status")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub status: Option, diff --git a/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs b/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs index cf213f4d6d76..596621970466 100644 --- a/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs +++ b/samples/server/petstore/rust-server/output/rust-server-test/src/models.rs @@ -12,9 +12,9 @@ use serde_valid::Validate; #[cfg_attr(feature = "conversion", derive(frunk::LabelledGeneric))] pub struct ANullableContainer { #[serde(rename = "NullableThing")] - #[serde(deserialize_with = "swagger::nullable_format::deserialize_optional_nullable")] #[serde(default = "swagger::nullable_format::default_optional_nullable")] + #[serde(skip_serializing_if="Option::is_none")] pub nullable_thing: Option>, @@ -214,6 +214,15 @@ impl std::ops::DerefMut for AdditionalPropertiesObject { } } +#[cfg(feature = "validate")] +impl serde_valid::validation::ValidateCompositedMinLength for AdditionalPropertiesObject { + fn validate_composited_min_length( + &self, + _min_length: usize, + ) -> Result<(), serde_valid::validation::Composited> { + Ok(()) + } +} /// Converts the AdditionalPropertiesObject value to the Query Parameters representation (style=form, explode=false) /// specified in /// Should be implemented in a serde serializer @@ -996,7 +1005,6 @@ impl std::convert::TryFrom for header::IntoHeaderVal pub struct ObjectOfObjects { #[serde(rename = "inner")] - #[cfg_attr(feature = "validate", validate)] #[cfg_attr(feature = "validate", validate)] #[serde(skip_serializing_if="Option::is_none")] pub inner: Option, @@ -1525,6 +1533,15 @@ impl std::ops::DerefMut for UnnamedReference { } } +#[cfg(feature = "validate")] +impl serde_valid::validation::ValidateCompositedMinLength for UnnamedReference { + fn validate_composited_min_length( + &self, + _min_length: usize, + ) -> Result<(), serde_valid::validation::Composited> { + Ok(()) + } +} /// Converts the UnnamedReference value to the Query Parameters representation (style=form, explode=false) /// specified in /// Should be implemented in a serde serializer