Skip to content

Commit ec9baf5

Browse files
Further rework
1 parent d6b6ba5 commit ec9baf5

File tree

2 files changed

+63
-49
lines changed

2 files changed

+63
-49
lines changed

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

Lines changed: 62 additions & 40 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,8 +70,6 @@ class OpenAPIModelRegistration(
6970
handleType(tpe)
7071
}
7172

72-
private case class OpenAPISimpleType(tpe: String, format: Option[String] = None)
73-
7473
@tailrec
7574
private def handleType(tpe: Type): Schema[_] = {
7675
if (extraTypesHandler.isDefinedAt(tpe)) handleExtraTypes(tpe)
@@ -96,8 +95,7 @@ class OpenAPIModelRegistration(
9695

9796
private def handleCaseType(tpe: Type): Schema[_] = {
9897
val name = tpe.typeSymbol.name.toString.trim
99-
val schema = new Schema
100-
schema.setType("object")
98+
val schema = new ObjectSchema
10199
val fields = tpe.decls.collect {
102100
case field: TermSymbol if field.isVal => field
103101
}
@@ -114,17 +112,15 @@ class OpenAPIModelRegistration(
114112

115113
private def handleMap(keyType: Type, valueType: Type): Schema[_] = keyType match {
116114
case _ if keyType <:< typeOf[String] =>
117-
val schema = new Schema
118-
schema.setType("object")
115+
val schema = new ObjectSchema
119116
schema.setAdditionalProperties(handleType(valueType))
120117
schema
121118
case _ => throw new IllegalArgumentException("In OpenAPI 3.0.x Map must have String key type.")
122119
}
123120

124121
private def handleSeqLike(tpe: Type): Schema[_] = {
125-
val schema = new Schema
122+
val schema = new ArraySchema
126123
val innerSchema = handleType(tpe.typeArgs.head)
127-
schema.setType("array")
128124
schema.setItems(innerSchema)
129125
schema
130126
}
@@ -139,8 +135,7 @@ class OpenAPIModelRegistration(
139135
val enumValues = parentObjectType.members.filter(isSymbolEnumerationValue)
140136
val enumValuesAsStrings = enumValues.map(_.name.toString.trim)
141137

142-
val schema = new Schema[String]
143-
schema.setType("string")
138+
val schema = new StringSchema
144139
schema.setEnum(enumValuesAsStrings.toList.asJava)
145140
schema
146141
}
@@ -197,7 +192,7 @@ class OpenAPIModelRegistration(
197192
// - case objects = registered as reference
198193
// - sealed trait/abstract class = registered as reference
199194
val childrenRefs = children.map(s => (new Schema).$ref(s.name.toString.trim)).toSeq
200-
val schema = new Schema
195+
val schema = new ObjectSchema
201196
schema.setOneOf(childrenRefs.asJava)
202197
val schemaRef = registerAsReference(name, schema)
203198
children.map(_.asType.toType).foreach(handleType)
@@ -223,34 +218,61 @@ class OpenAPIModelRegistration(
223218
}
224219
}
225220

226-
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
232-
}
233-
234-
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")
221+
private def handleSimpleType(tpe: Type): Schema[_] = tpe.dealias match {
222+
case t if t =:= typeOf[Byte] =>
223+
val s = new IntegerSchema()
224+
s.setFormat("int32")
225+
s
226+
case t if t =:= typeOf[Short] =>
227+
val s = new IntegerSchema()
228+
s.setFormat("int32")
229+
s
230+
case t if t =:= typeOf[Int] =>
231+
val s = new IntegerSchema()
232+
s.setFormat("int32")
233+
s
234+
case t if t =:= typeOf[Long] =>
235+
val s = new IntegerSchema()
236+
s.setFormat("int64")
237+
s
238+
case t if t =:= typeOf[Float] =>
239+
val s = new NumberSchema()
240+
s.setFormat("float")
241+
s
242+
case t if t =:= typeOf[Double] =>
243+
val s = new NumberSchema()
244+
s.setFormat("double")
245+
s
246+
case t if t =:= typeOf[Char] =>
247+
new StringSchema()
248+
case t if t =:= typeOf[String] =>
249+
new StringSchema()
250+
case t if t =:= typeOf[UUID] =>
251+
val s = new UUIDSchema()
252+
s.setFormat("uuid")
253+
s
254+
case t if t =:= typeOf[Boolean] =>
255+
new BooleanSchema()
256+
case t if t =:= typeOf[Unit] =>
257+
val s = new Schema[Unit]()
258+
s.setType("null")
259+
s
260+
case t if t =:= typeOf[ZonedDateTime] || t =:= typeOf[Instant] || t =:= typeOf[LocalDateTime] || t =:= typeOf[Timestamp] =>
261+
val s = new StringSchema()
262+
s.setFormat("date-time")
263+
s
264+
case t if t =:= typeOf[LocalDate] =>
265+
val s = new StringSchema()
266+
s.setFormat("date")
267+
s
268+
case t if t =:= typeOf[LocalTime] =>
269+
val s = new StringSchema()
270+
s.setFormat("time")
271+
s
272+
case t if t =:= typeOf[BigDecimal] =>
273+
new NumberSchema()
274+
case t if t =:= typeOf[BigInt] =>
275+
new IntegerSchema()
254276
}
255277

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

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
package za.co.absa.springdocopenapiscala
1818

19-
import io.swagger.v3.core.util.Json
2019
import io.swagger.v3.oas.models.{Components, OpenAPI}
2120
import za.co.absa.springdocopenapiscala.SpringdocOpenAPIVersionSpecificTypes.OpenApiCustomizer
2221

@@ -25,16 +24,9 @@ import scala.collection.JavaConverters._
2524
class OpenAPIScalaCustomizer(components: Components) extends OpenApiCustomizer {
2625

2726
override def customise(openAPIOutOfSync: OpenAPI): Unit = {
28-
// Serialize the customized Components object to a JSON string.
29-
val jsonRepresentation = Json.pretty(components)
30-
31-
// Deserialize the JSON string back into a new Components object to iron out any issues.
32-
val newComponents = Json.mapper().readValue(jsonRepresentation, classOf[Components])
33-
34-
// Finally replace the Components object in the OpenAPI instance.
3527
// This is needed as for some reason springdoc-openapi cache the `OpenAPI` at the beginning
3628
// and newly added `Components` are not taken into account on JSON/YAML generation.
37-
openAPIOutOfSync.setComponents(newComponents)
29+
openAPIOutOfSync.setComponents(components)
3830

3931
fixResponsesReturningUnit(openAPIOutOfSync)
4032
}

0 commit comments

Comments
 (0)