Skip to content

Commit e253416

Browse files
committed
Handle inlined objects before references for better required support
Some API definitions define whether a property is required or not at a place different to the object where the property itself is defined, this is now supported.
1 parent c856db3 commit e253416

File tree

2 files changed

+24
-14
lines changed

2 files changed

+24
-14
lines changed

openapigenerator/src/jvmMain/kotlin/net/axay/openapigenerator/ClassBuilderHolder.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ class ClassBuilderHolder(
99
val classBuilder: TypeSpec.Builder,
1010
val constructorBuilder: FunSpec.Builder,
1111
) {
12+
val requiredProps = HashSet<String>()
1213
val handledSuperTypes = HashSet<String>()
1314

1415
fun build() = classBuilder

openapigenerator/src/jvmMain/kotlin/net/axay/openapigenerator/SchemaGeneration.kt

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,27 @@ internal fun Generator.handleTopLevelSchema(schemaName: String, schemaObject: Js
4242
fileBuilder.build().writeTo(targetDirectory)
4343
}
4444

45-
internal fun Generator.handleObject(builder: ClassBuilderHolder, objectName: String, schemaObject: JsonObject, recursive: Boolean = true) {
45+
internal fun Generator.handleObject(
46+
builder: ClassBuilderHolder,
47+
objectName: String,
48+
schemaObject: JsonObject,
49+
recursive: Boolean = true,
50+
) {
4651
if ("allOf" in schemaObject) {
47-
for (allOfObject in schemaObject["allOf"]!!.jsonArray.map { it.jsonObject }) {
48-
if (ref in allOfObject) {
49-
val refObjectName = allOfObject[ref]!!.jsonPrimitive.content.withoutSchemaPrefix()
50-
if (refObjectName !in builder.handledSuperTypes) {
51-
handleObject(builder, refObjectName, schemaObjects[refObjectName]!!, recursive = false)
52-
builder.handledSuperTypes += refObjectName
53-
}
54-
} else {
55-
handleObject(builder, objectName, allOfObject, recursive)
52+
val objects = mutableListOf<JsonObject>()
53+
val references = mutableListOf<JsonObject>()
54+
55+
schemaObject["allOf"]!!.jsonArray.map { it.jsonObject }.forEach { allOfObject ->
56+
(if (ref in allOfObject) references else objects) += allOfObject
57+
}
58+
59+
objects.forEach { allOfObject ->
60+
handleObject(builder, objectName, allOfObject, recursive)
61+
}
62+
references.forEach { refObject ->
63+
val refObjectName = refObject[ref]!!.jsonPrimitive.content.withoutSchemaPrefix()
64+
if (builder.handledSuperTypes.add(refObjectName)) {
65+
handleObject(builder, refObjectName, schemaObjects[refObjectName]!!, recursive = false)
5666
}
5767
}
5868
return
@@ -135,14 +145,13 @@ internal fun Generator.handleObject(builder: ClassBuilderHolder, objectName: Str
135145
error("Unknown type '$propTypeName' defined for '$propName' in object '$objectName'. Full property: $typeObject")
136146
}
137147

138-
val requiredProps = schemaObject["required"]?.jsonArray
139-
?.map { it.jsonPrimitive.content } ?: emptyList()
148+
builder.requiredProps += (schemaObject["required"]?.jsonArray?.map { it.jsonPrimitive.content }.orEmpty())
140149

141150
val propObjects = schemaObject["properties"]?.jsonObject?.mapValues { it.value.jsonObject }
142151
propObjects?.forEach { (propName, propObject) ->
143152

144153
val propType = typeFrom(propObject, propName)
145-
.copy(nullable = propName !in requiredProps || propObject["nullable"]?.jsonPrimitive?.boolean == true)
154+
.copy(nullable = propName !in builder.requiredProps || propObject["nullable"]?.jsonPrimitive?.boolean == true)
146155

147156
val camelCasePropName = propName.toCamelCase()
148157

@@ -155,7 +164,7 @@ internal fun Generator.handleObject(builder: ClassBuilderHolder, objectName: Str
155164
.addMember("\"$propName\"")
156165
.build()
157166
)
158-
if (propName !in requiredProps)
167+
if (propName !in builder.requiredProps)
159168
defaultValue("null")
160169
}
161170
.build()

0 commit comments

Comments
 (0)