Skip to content

Commit b8d2f33

Browse files
committed
#24, find nested schemas of additionalProperties
(cherry picked from commit 511bf30)
1 parent 3f831fd commit b8d2f33

9 files changed

Lines changed: 151 additions & 0 deletions

File tree

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/converter/DataTypeConverter.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,12 @@ class DataTypeConverter(
242242
properties[propName] = propDataType
243243
}
244244

245+
// navigate additionalProperties to find nested schemas
246+
val additionalSchemaInfo = schemaInfo.buildForAdditionalProperties()
247+
if (additionalSchemaInfo != null) {
248+
convert(additionalSchemaInfo, dataTypes)
249+
}
250+
245251
val objectType = createObjectDataType(schemaInfo, properties)
246252

247253
val targetType = getMappedDataType(schemaInfo)

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/converter/SchemaInfo.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,21 @@ open class SchemaInfo(
328328
)
329329
}
330330

331+
/**
332+
* Factory method to create an {@link SchemaInfo} of additionalProperties.
333+
*
334+
* @return a new {@link SchemaInfo}
335+
*/
336+
fun buildForAdditionalProperties(): SchemaInfo? {
337+
val additionalProperties = schema?.getAdditionalProperties() ?: return null
338+
339+
return SchemaInfo(
340+
endpoint = endpoint,
341+
name = getNestedTypeName("additionalProperties"),
342+
schema = additionalProperties,
343+
resolver = resolver)
344+
}
345+
331346
override fun isPrimitive(): Boolean {
332347
return listOf("boolean", "integer", "number", "string").contains(schema?.getType())
333348
}

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/parser/Schema.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ interface Schema {
2424

2525
// object
2626
fun getProperties(): Map<String, Schema>
27+
fun getAdditionalProperties(): Schema?
2728

2829
// composed object
2930
fun getItems(): List<Schema>

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/parser/openapi/v30/Schema.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ class Schema(val schema: Schema30) : ParserSchema {
7272
return props
7373
}
7474

75+
override fun getAdditionalProperties(): Schema? {
76+
val additional = schema.additionalProperties
77+
78+
// null, boolean, schema
79+
if(additional is Schema30) {
80+
return Schema(additional)
81+
}
82+
83+
return null;
84+
}
85+
7586
override fun getItems(): List<ParserSchema> {
7687
val result: MutableList<ParserSchema> = mutableListOf()
7788

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/parser/openapi/v31/Schema.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ class Schema(val schema: Schema31) : ParserSchema {
7272
return props
7373
}
7474

75+
override fun getAdditionalProperties(): Schema? {
76+
val additional = schema.additionalProperties
77+
78+
// null, boolean, schema
79+
if(additional is Schema31) {
80+
return Schema(additional)
81+
}
82+
83+
return null;
84+
}
85+
7586
override fun getItems(): List<ParserSchema> {
7687
val result: MutableList<ParserSchema> = mutableListOf()
7788

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/parser/openapi4j/Schema.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,17 @@ class Schema(val schema: O4jSchema) : ParserSchema {
4343
return props
4444
}
4545

46+
override fun getAdditionalProperties(): Schema? {
47+
val additional = schema.additionalProperties
48+
49+
// null, boolean, schema
50+
if(additional is O4jSchema) {
51+
return Schema(additional)
52+
}
53+
54+
return null;
55+
}
56+
4657
override fun getItems(): List<ParserSchema> {
4758
val result: MutableList<ParserSchema> = mutableListOf()
4859

openapi-processor-core/src/main/kotlin/io/openapiprocessor/core/parser/swagger/Schema.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,17 @@ class Schema(private val schema: SwaggerSchema<*>): ParserSchema {
4545
return props
4646
}
4747

48+
override fun getAdditionalProperties(): ParserSchema? {
49+
val additional = schema.additionalProperties
50+
51+
// null, boolean, schema
52+
if(additional is SwaggerSchema<*>) {
53+
return Schema(additional)
54+
}
55+
56+
return null;
57+
}
58+
4859
override fun getItems(): List<ParserSchema> {
4960
val result: MutableList<ParserSchema> = mutableListOf()
5061

openapi-processor-core/src/test/groovy/com/github/hauner/openapi/core/test/TestSchema.groovy

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,9 @@ class TestSchema implements Schema {
7979
boolean getWriteOnly () {
8080
return false
8181
}
82+
83+
@Override
84+
Schema getAdditionalProperties() {
85+
return null
86+
}
8287
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright 2023 https://github.com/openapi-processor/openapi-processor-base
3+
* PDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.openapiprocessor.core.parser.swagger
7+
8+
import io.kotest.core.spec.IsolationMode
9+
import io.kotest.core.spec.style.StringSpec
10+
import io.kotest.matchers.nulls.shouldBeNull
11+
import io.kotest.matchers.nulls.shouldNotBeNull
12+
import io.openapiprocessor.core.model.HttpMethod
13+
import io.openapiprocessor.core.parser.ParserType
14+
import io.openapiprocessor.core.support.getSchemaInfo
15+
import io.openapiprocessor.core.support.parse
16+
17+
class AdditionalPropertiesSpec: StringSpec({
18+
isolationMode = IsolationMode.InstancePerTest
19+
20+
"additionalProperties of empty object is empty object" {
21+
val openApi = parse("""
22+
openapi: 3.0.2
23+
info:
24+
title: API
25+
version: 1.0.0
26+
27+
paths:
28+
/values:
29+
get:
30+
description: query object dictionary
31+
responses:
32+
'200':
33+
description: dictionary response
34+
content:
35+
application/json:
36+
schema:
37+
type: object
38+
additionalProperties: {}
39+
40+
""".trimIndent(), ParserType.SWAGGER
41+
)
42+
43+
44+
val schemaInfo = openApi.getSchemaInfo("Values",
45+
"/values", HttpMethod.GET, "200", "application/json")
46+
47+
val additional = schemaInfo.buildForAdditionalProperties()
48+
additional.shouldNotBeNull()
49+
}
50+
51+
"additionalProperties of boolean object is null" {
52+
val openApi = parse("""
53+
openapi: 3.0.2
54+
info:
55+
title: API
56+
version: 1.0.0
57+
58+
paths:
59+
/values:
60+
get:
61+
description: query object dictionary
62+
responses:
63+
'200':
64+
description: dictionary response
65+
content:
66+
application/json:
67+
schema:
68+
type: object
69+
additionalProperties: true
70+
71+
""".trimIndent(), ParserType.SWAGGER
72+
)
73+
74+
val schemaInfo = openApi.getSchemaInfo("Values",
75+
"/values", HttpMethod.GET, "200", "application/json")
76+
77+
val additional = schemaInfo.buildForAdditionalProperties()
78+
additional.shouldBeNull()
79+
}
80+
})

0 commit comments

Comments
 (0)