Skip to content

Commit ebdbbc2

Browse files
Fix schema types seriallization (#65)
* Fix String/Boolean serialization (serialize to Any). Fix optional/mandatory specification for all types * Test no longer applicable * Reassign only components property * Rework * Further rework * Restore unit test * wip * Fix BigInt * Fix Maps test * Mad code * Minor refactoring * review suggestion
1 parent 570d482 commit ebdbbc2

File tree

5 files changed

+42
-39
lines changed

5 files changed

+42
-39
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ The library has springdoc-openapi as a provided dependency,
3232
thus users of the library have to include that dependency in their projects:
3333
- for springdoc-openapi 1.x versions `1.6.7` up to `1.7.0` (including) of
3434
`"org.springdoc" % "springdoc-openapi-webmvc-core"` are supported
35-
- for springdoc-openapi 2.x versions `2.0.0` up to `2.3.0` (including) of
35+
- for springdoc-openapi 2.x versions `2.0.0` up to `2.8.9` (including) of
3636
`"org.springdoc" % "springdoc-openapi-starter-webmvc-api"` are supported
3737

3838
### Add library dependency to SBT/Maven

examples/springdoc-openapi-scala-2/simple/build.sbt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ lazy val root = (project in file("."))
2222
.settings(
2323
libraryDependencies ++= Seq(
2424
"za.co.absa" %% "springdoc-openapi-scala-2" % `springdoc-openapi-scala-2-version`,
25-
"org.springdoc" % "springdoc-openapi-starter-webmvc-api" % "2.3.0",
25+
"org.springdoc" % "springdoc-openapi-starter-webmvc-api" % "2.8.9",
2626
"org.springframework.boot" % "spring-boot-starter-web" % "3.2.0",
2727
"org.playframework" %% "play-json" % "3.0.1"
2828
),

library/src/main/scala/za/co/absa/springdocopenapiscala/OpenAPIModelRegistration.scala

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package za.co.absa.springdocopenapiscala
1818

1919
import io.swagger.v3.oas.models.Components
20-
import io.swagger.v3.oas.models.media.{Discriminator, Schema}
20+
import io.swagger.v3.oas.models.media.{ArraySchema, BooleanSchema, Discriminator, IntegerSchema, NumberSchema, ObjectSchema, Schema, StringSchema, UUIDSchema}
2121

2222
import java.time.{Instant, LocalDate, LocalDateTime, LocalTime, ZonedDateTime}
2323
import java.util.UUID
@@ -27,6 +27,7 @@ import scala.reflect.runtime.universe._
2727
import OpenAPIModelRegistration._
2828

2929
import java.sql.Timestamp
30+
import scala.collection.Seq
3031

3132
class OpenAPIModelRegistration(
3233
components: Components,
@@ -69,7 +70,7 @@ class OpenAPIModelRegistration(
6970
handleType(tpe)
7071
}
7172

72-
private case class OpenAPISimpleType(tpe: String, format: Option[String] = None)
73+
private case class OpenAPISimpleType(schema: Schema[_], format: Option[String] = None, _type: Option[String] = None)
7374

7475
@tailrec
7576
private def handleType(tpe: Type): Schema[_] = {
@@ -96,8 +97,7 @@ class OpenAPIModelRegistration(
9697

9798
private def handleCaseType(tpe: Type): Schema[_] = {
9899
val name = tpe.typeSymbol.name.toString.trim
99-
val schema = new Schema
100-
schema.setType("object")
100+
val schema = new ObjectSchema
101101
val fields = tpe.decls.collect {
102102
case field: TermSymbol if field.isVal => field
103103
}
@@ -114,17 +114,15 @@ class OpenAPIModelRegistration(
114114

115115
private def handleMap(keyType: Type, valueType: Type): Schema[_] = keyType match {
116116
case _ if keyType <:< typeOf[String] =>
117-
val schema = new Schema
118-
schema.setType("object")
117+
val schema = new ObjectSchema
119118
schema.setAdditionalProperties(handleType(valueType))
120119
schema
121120
case _ => throw new IllegalArgumentException("In OpenAPI 3.0.x Map must have String key type.")
122121
}
123122

124123
private def handleSeqLike(tpe: Type): Schema[_] = {
125-
val schema = new Schema
124+
val schema = new ArraySchema
126125
val innerSchema = handleType(tpe.typeArgs.head)
127-
schema.setType("array")
128126
schema.setItems(innerSchema)
129127
schema
130128
}
@@ -139,8 +137,7 @@ class OpenAPIModelRegistration(
139137
val enumValues = parentObjectType.members.filter(isSymbolEnumerationValue)
140138
val enumValuesAsStrings = enumValues.map(_.name.toString.trim)
141139

142-
val schema = new Schema[String]
143-
schema.setType("string")
140+
val schema = new StringSchema
144141
schema.setEnum(enumValuesAsStrings.toList.asJava)
145142
schema
146143
}
@@ -224,33 +221,39 @@ class OpenAPIModelRegistration(
224221
}
225222

226223
private def handleSimpleType(tpe: Type): Schema[_] = {
227-
val schema = new Schema
228-
val OpenAPISimpleType(terminalTpe, format) = getOpenAPISimpleType(tpe)
229-
schema.setType(terminalTpe)
230-
format.foreach(f => schema.setFormat(f))
231-
schema
224+
val simpleType = getOpenAPISimpleType(tpe)
225+
simpleType.format.foreach(simpleType.schema.setFormat)
226+
simpleType._type.foreach(simpleType.schema.setType)
227+
simpleType.schema
232228
}
233229

234230
private def getOpenAPISimpleType(tpe: Type): OpenAPISimpleType = tpe.dealias match {
235-
case t if t =:= typeOf[Byte] => OpenAPISimpleType("integer", Some("int32"))
236-
case t if t =:= typeOf[Short] => OpenAPISimpleType("integer", Some("int32"))
237-
case t if t =:= typeOf[Int] => OpenAPISimpleType("integer", Some("int32"))
238-
case t if t =:= typeOf[Long] => OpenAPISimpleType("integer", Some("int64"))
239-
case t if t =:= typeOf[Float] => OpenAPISimpleType("number", Some("float"))
240-
case t if t =:= typeOf[Double] => OpenAPISimpleType("number", Some("double"))
241-
case t if t =:= typeOf[Char] => OpenAPISimpleType("string")
242-
case t if t =:= typeOf[String] => OpenAPISimpleType("string")
243-
case t if t =:= typeOf[UUID] => OpenAPISimpleType("string", Some("uuid"))
244-
case t if t =:= typeOf[Boolean] => OpenAPISimpleType("boolean")
245-
case t if t =:= typeOf[Unit] => OpenAPISimpleType("null")
246-
case t if t =:= typeOf[ZonedDateTime] => OpenAPISimpleType("string", Some("date-time"))
247-
case t if t =:= typeOf[Instant] => OpenAPISimpleType("string", Some("date-time"))
248-
case t if t =:= typeOf[LocalDateTime] => OpenAPISimpleType("string", Some("date-time"))
249-
case t if t =:= typeOf[LocalDate] => OpenAPISimpleType("string", Some("date"))
250-
case t if t =:= typeOf[LocalTime] => OpenAPISimpleType("string", Some("time"))
251-
case t if t =:= typeOf[Timestamp] => OpenAPISimpleType("string", Some("date-time"))
252-
case t if t =:= typeOf[BigDecimal] => OpenAPISimpleType("number")
253-
case t if t =:= typeOf[BigInt] => OpenAPISimpleType("integer")
231+
case t if t =:= typeOf[Byte] || t =:= typeOf[Short] || t =:= typeOf[Int] =>
232+
OpenAPISimpleType(new IntegerSchema())
233+
case t if t =:= typeOf[Long] =>
234+
OpenAPISimpleType(new IntegerSchema(), Some("int64"))
235+
case t if t =:= typeOf[Float] =>
236+
OpenAPISimpleType(new NumberSchema(), Some("float"))
237+
case t if t =:= typeOf[Double] =>
238+
OpenAPISimpleType(new NumberSchema(), Some("double"))
239+
case t if t =:= typeOf[Char] || t =:= typeOf[String] =>
240+
OpenAPISimpleType(new StringSchema())
241+
case t if t =:= typeOf[UUID] =>
242+
OpenAPISimpleType(new UUIDSchema())
243+
case t if t =:= typeOf[Boolean] =>
244+
OpenAPISimpleType(new BooleanSchema())
245+
case t if t =:= typeOf[Unit] =>
246+
OpenAPISimpleType(new Schema, None, Some("null"))
247+
case t if t =:= typeOf[ZonedDateTime] || t =:= typeOf[Instant] || t =:= typeOf[LocalDateTime] || t =:= typeOf[Timestamp] =>
248+
OpenAPISimpleType(new StringSchema(), Some("date-time"))
249+
case t if t =:= typeOf[LocalDate] =>
250+
OpenAPISimpleType(new StringSchema(), Some("date"))
251+
case t if t =:= typeOf[LocalTime] =>
252+
OpenAPISimpleType(new StringSchema(), Some("time"))
253+
case t if t =:= typeOf[BigDecimal] =>
254+
OpenAPISimpleType(new NumberSchema())
255+
case t if t =:= typeOf[BigInt] =>
256+
OpenAPISimpleType(new IntegerSchema(), Some(null))
254257
}
255258

256259
private def registerAsReference(name: String, schema: Schema[_]): Schema[_] = {

library/src/test/scala/za/co/absa/springdocopenapiscala/OpenAPIModelRegistrationSpec.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
package za.co.absa.springdocopenapiscala
1818

1919
import io.swagger.v3.oas.models.Components
20-
import io.swagger.v3.oas.models.media.Schema
20+
import io.swagger.v3.oas.models.media.{IntegerSchema, Schema}
2121
import org.scalatest
2222
import org.scalatest.flatspec.AnyFlatSpec
2323

@@ -281,7 +281,7 @@ class OpenAPIModelRegistrationSpec extends AnyFlatSpec {
281281
assertAdditionalPropertiesAreAsExpected(
282282
actualSchemas,
283283
"Maps.a",
284-
(new Schema).`type`("integer").format("int32")
284+
new IntegerSchema()
285285
)
286286
assertTypeAndFormatAreAsExpected(actualSchemas, "Maps.b", "object")
287287
assertAdditionalPropertiesAreAsExpected(

project/Dependencies.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ object Dependencies {
2727

2828
def springdocOpenapi(majorVersion: Int): String = majorVersion match {
2929
case 1 => "[1.6.7,1.7.0]"
30-
case 2 => "[2.0.0,2.3.0]"
30+
case 2 => "[2.0.0,2.8.9]"
3131
}
3232
}
3333

0 commit comments

Comments
 (0)