Skip to content

Commit e406821

Browse files
authored
#56 Disallow non-String type key in Map and add info about values type (#57)
1 parent 76f9c4d commit e406821

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

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

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ class OpenAPIModelRegistration(
7777
else
7878
tpe.dealias match {
7979
case t if tpe.typeSymbol.isClass && tpe.typeSymbol.asClass.isCaseClass => handleCaseType(t)
80-
case t if t <:< typeOf[Map[_, _]] => handleMap(t)
81-
case t if t <:< typeOf[Option[_]] => handleType(t.typeArgs.head)
82-
case t if t <:< typeOf[Seq[_]] || t <:< typeOf[Array[_]] => handleSeqLike(t)
83-
case t if t <:< typeOf[Set[_]] => handleSet(t)
84-
case t if t <:< typeOf[Enumeration#Value] => handleEnum(t)
85-
case t if t.typeSymbol.isClass && t.typeSymbol.asClass.isSealed => handleSealedType(t)
86-
case t => handleSimpleType(t)
80+
case t if t <:< typeOf[Map[_, _]] => handleMap(t.typeArgs(0), t.typeArgs(1))
81+
case t if t <:< typeOf[Option[_]] => handleType(t.typeArgs.head)
82+
case t if t <:< typeOf[Seq[_]] || t <:< typeOf[Array[_]] => handleSeqLike(t)
83+
case t if t <:< typeOf[Set[_]] => handleSet(t)
84+
case t if t <:< typeOf[Enumeration#Value] => handleEnum(t)
85+
case t if t.typeSymbol.isClass && t.typeSymbol.asClass.isSealed => handleSealedType(t)
86+
case t => handleSimpleType(t)
8787
}
8888
}
8989

@@ -112,10 +112,13 @@ class OpenAPIModelRegistration(
112112
registerAsReference(name, schema)
113113
}
114114

115-
private def handleMap(tpe: Type): Schema[_] = {
116-
val schema = new Schema
117-
schema.setType("object")
118-
schema
115+
private def handleMap(keyType: Type, valueType: Type): Schema[_] = keyType match {
116+
case _ if keyType <:< typeOf[String] =>
117+
val schema = new Schema
118+
schema.setType("object")
119+
schema.setAdditionalProperties(handleType(valueType))
120+
schema
121+
case _ => throw new IllegalArgumentException("In OpenAPI 3.0.x Map must have String key type.")
119122
}
120123

121124
private def handleSeqLike(tpe: Type): Schema[_] = {

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

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,12 @@ class OpenAPIModelRegistrationSpec extends AnyFlatSpec {
8080

8181
private case class Maps(
8282
a: Map[String, Int],
83-
b: Map[Int, Arrays]
83+
b: Map[String, Arrays]
84+
)
85+
86+
private case class WrongMaps(
87+
a: Map[Int, Int],
88+
b: Map[Boolean, Arrays]
8489
)
8590

8691
private object Things extends Enumeration {
@@ -262,7 +267,7 @@ class OpenAPIModelRegistrationSpec extends AnyFlatSpec {
262267
assertIsArrayOfExpectedType(actualSchemas, "Arrays.h", "integer")
263268
}
264269

265-
it should "make Map an OpenAPI object type" in {
270+
it should "make Map an OpenAPI object type with value schema as additionalProperties" in {
266271
val components = new Components
267272
val openAPIModelRegistration = new OpenAPIModelRegistration(components)
268273

@@ -271,7 +276,26 @@ class OpenAPIModelRegistrationSpec extends AnyFlatSpec {
271276
val actualSchemas = components.getSchemas
272277

273278
assertTypeAndFormatAreAsExpected(actualSchemas, "Maps.a", "object")
279+
assertAdditionalPropertiesAreAsExpected(
280+
actualSchemas,
281+
"Maps.a",
282+
(new Schema).`type`("integer").format("int32")
283+
)
274284
assertTypeAndFormatAreAsExpected(actualSchemas, "Maps.b", "object")
285+
assertAdditionalPropertiesAreAsExpected(
286+
actualSchemas,
287+
"Maps.b",
288+
(new Schema).$ref("#/components/schemas/Arrays")
289+
)
290+
}
291+
292+
it should "throw IllegalArgumentException if Map has key type different than String" in {
293+
val components = new Components
294+
val openAPIModelRegistration = new OpenAPIModelRegistration(components)
295+
296+
intercept[IllegalArgumentException] {
297+
openAPIModelRegistration.register[WrongMaps]()
298+
}
275299
}
276300

277301
it should "make simple Enumeration (without renaming) an OpenAPI enum" in {
@@ -805,6 +829,16 @@ class OpenAPIModelRegistrationSpec extends AnyFlatSpec {
805829
schema => schema.getType === expectedType && Option(schema.getFormat) === expectedFormat
806830
)
807831

832+
private def assertAdditionalPropertiesAreAsExpected(
833+
actualSchemas: java.util.Map[String, Schema[_]],
834+
fieldPath: String,
835+
expectedAdditionalProperties: AnyRef
836+
): scalatest.Assertion = assertPredicateForPath(
837+
actualSchemas,
838+
fieldPath,
839+
schema => Option(schema.getAdditionalProperties).map(_ === expectedAdditionalProperties).getOrElse(false)
840+
)
841+
808842
private def assertRefIsAsExpected(
809843
actualSchemas: java.util.Map[String, Schema[_]],
810844
fieldPath: String,

0 commit comments

Comments
 (0)