Skip to content

Commit 19625fc

Browse files
authored
codegen: fix validator generation for nullable fields (#4937)
Exclude 'nullable' fields when 'wrapping' them in generated validators (the validators on nullable types already assume the value is an Option, so treating them optionally twice generates non-compiling code) Closes #4933
1 parent d1806a8 commit 19625fc

File tree

3 files changed

+16
-11
lines changed

3 files changed

+16
-11
lines changed

openapi-codegen/core/src/main/scala/sttp/tapir/codegen/ValidationGenerator.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ object ValidationGenerator {
5555
val allSchemas = doc.components.map(_.schemas).getOrElse(Map.empty)
5656

5757
// All schemas that have explicit validation _or_ refer to a ref, which _may_ have.
58-
// We need to filter this, because we may have trivial
58+
// We need to filter this, because we may have recursive references that don't contain any 'real' validation
5959
val unfiltered = {
6060
val mapped = allSchemas.flatMap { case (k, v) => genValidationDefn(allSchemas, ignoreRefs = false)(k, v).filterNot(_.refOnly) }
6161
if (mapped.isEmpty) ValidationDefns.empty
@@ -272,7 +272,8 @@ object ValidationGenerator {
272272
fn,
273273
(
274274
defn,
275-
f.`type`.nullable || !rs.contains(fn),
275+
// exclude non-required 'nullable' here because the field validators will already treat the value as optional
276+
!rs.contains(fn) && !f.`type`.nullable,
276277
f.`type`
277278
)
278279
)

openapi-codegen/sbt-plugin/src/sbt-test/sbt-openapi-codegen/oneOf-json-roundtrip/ExpectedValidators.scala.txt

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ object TapirGeneratedEndpointsValidators {
1212
errs.flatMap(_.customMessage).toList
1313
ValidationResult.Invalid(msgs)
1414
}
15+
), Validator.custom(
16+
(obj: ValidatedObj) => ValidatedObjQuuxValidator.apply(obj.quux) match {
17+
case Nil => ValidationResult.Valid
18+
case errs =>
19+
val msgs: List[String] = "Object element validation failed for ValidatedObj.quux" +:
20+
errs.flatMap(_.customMessage).toList
21+
ValidationResult.Invalid(msgs)
22+
}
1523
), Validator.custom(
1624
(obj: ValidatedObj) => ValidatedSubObjValidator.apply(obj.bar) match {
1725
case Nil => ValidationResult.Valid
@@ -52,14 +60,6 @@ object TapirGeneratedEndpointsValidators {
5260
errs.flatMap(_.customMessage).toList
5361
ValidationResult.Invalid(msgs)
5462
}
55-
), Validator.custom(
56-
(obj: ValidatedObj) => obj.quux.toSeq.flatMap(ValidatedObjQuuxValidator.apply) match {
57-
case Nil => ValidationResult.Valid
58-
case errs =>
59-
val msgs: List[String] = "Object element validation failed for ValidatedObj.quux" +:
60-
errs.flatMap(_.customMessage).toList
61-
ValidationResult.Invalid(msgs)
62-
}
6363
), Validator.custom(
6464
(obj: ValidatedObj) => obj.rec.toSeq.flatMap(ValidatedRecursiveValidator.apply) match {
6565
case Nil => ValidationResult.Valid
@@ -100,7 +100,10 @@ object TapirGeneratedEndpointsValidators {
100100
}
101101
), Validator.maxSize(12), Validator.minSize(3))
102102
lazy val ValidatedObjMapItemValidator: Validator[Int] = Validator.all(Validator.max(900, exclusive = true), Validator.min(0, exclusive = false))
103-
lazy val ValidatedObjQuuxValidator: Validator[String] = Validator.maxLength(128)
103+
lazy val ValidatedObjQuuxValidator: Validator[Option[String]] = Validator.custom[Option[String]](ot => ot.map(Validator.maxLength(128)(_)).map{
104+
case Nil => ValidationResult.Valid
105+
case l => ValidationResult.Invalid(l.flatMap(_.customMessage).toList)
106+
}.getOrElse(ValidationResult.Valid))
104107
lazy val ValidatedObjSetValidator: Validator[Set[String]] = Validator.maxSize(9)
105108
lazy val ValidatedOneOfValidator: Validator[ValidatedOneOf] = Validator.custom(
106109
(obj: ValidatedOneOf) => (obj match {

openapi-codegen/sbt-plugin/src/sbt-test/sbt-openapi-codegen/oneOf-json-roundtrip/swagger.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,7 @@ components:
11351135
quux:
11361136
type: string
11371137
maxLength: 128
1138+
nullable: true
11381139
map:
11391140
type: object
11401141
additionalProperties:

0 commit comments

Comments
 (0)