OpenAPITools / OpenAPITools/openapi-generator
[BUG] [Kotlin] Missing string array check for validity
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
openapi-generator version
7.13.0
OpenAPI declaration file content or url
"data": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/LocationDataTemperature"
},
{
"$ref": "#/components/schemas/LocationDataWind"
}
]
}
},
"LocationDataTemperature": {
"type": "object",
"properties": {
"display": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["display"]
},
"LocationDataWind": {
"type": "object",
"properties": {
"display": {
"type": "array",
"items": {
"type": "object",
"properties": {
"FF_KMH": {
"type": "number",
"format": "float"
},
"FX_KMH": {
"type": "number",
"format": "float"
},
"DD_DEG": {
"type": "integer"
}
},
"required": ["FF_KMH", "FX_KMH", "DD_DEG"]
}
}
},
"required": ["display"]
Generation Details
Gradle Task
val meteoMapApiName = "MeteoMap"
val meteoMapApiGenPackage = "${project.android.namespace}.${meteoMapApiName.lowercase()}"
val generateMeteoMap by registering(GenerateTask::class) {
generatorName.set("kotlin")
inputSpec.set("${project.projectDir}/${meteoMapApiName.lowercase()}-api.json")
outputDir.set("$buildDir/generated")
packageName.set(meteoMapApiGenPackage)
apiPackage.set("$meteoMapApiGenPackage.api")
modelNamePrefix.set(meteoMapApiName)
invokerPackage.set("$meteoMapApiGenPackage.invoker")
modelPackage.set("$meteoMapApiGenPackage.model")
configOptions.set(apiConfigOptions)
additionalProperties.set(
mapOf(
"enumPropertyNaming" to "UPPERCASE",
"useCoroutines" to "true",
"moshiCodeGen" to "true",
"generateOneOfAnyOfWrappers" to "true",
"serializationLibrary" to "gson",
),
)
library.set("jvm-retrofit2")
}
Steps to reproduce
When we receive a response from the server and parse it's body, an exception is thrown. Because too many Type Adapters match with the result.
Example of a json response:
"display": [
{
"FF_KMH": 4,
"FX_KMH": 7,
"DD_DEG": 212,
"dateTime": "2025-05-15T00:00:00+00:00"
}
]
This should obviousley only match to the type of LocationDataWind according to the schema provided above, but also the type of LocationDataTemperature apparantly does match the result. So I checked out the LocationDataTemperature.validateJsonElement() function.
@Throws(IOException::class)
fun validateJsonElement(jsonElement: JsonElement?) {
if (jsonElement == null) {
require(openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null
String.format("The required field(s) %s in MeteoMapLocationDataTemperature is not found in the empty JSON string", MeteoMapLocationDataTemperature.openapiRequiredFields.toString())
}
}
// check to make sure all required properties/fields are present in the JSON string
for (requiredField in openapiRequiredFields) {
requireNotNull(jsonElement!!.getAsJsonObject()[requiredField]) {
String.format("The required field `%s` is not found in the JSON string: %s", requiredField, jsonElement.toString())
}
}
val jsonObj = jsonElement!!.getAsJsonObject()
// ensure the required json array is present
requireNotNull(jsonObj["display"]) {
"Expected the field `display` to be an array in the JSON string but got `null`"
}
require(jsonObj["display"].isJsonArray()) {
String.format("Expected the field `display` to be an array in the JSON string but got `%s`", jsonObj["display"].toString())
}
}
It looks like the validate function here only checks if an array is present and then declares the json as valid. It does not check if the items inside the array are actual strings. This check is just simply missing. In the LocationDataWind.validateJsonElement() function there is such a check implemented:
for (i in 0 until jsonObj.getAsJsonArray("display").size()) {
MeteoMapLocationDataWindDisplayInner.validateJsonElement(jsonObj.getAsJsonArray("display").get(i))
}
Suggest a fix
If there is a list of strings, the validateJsonElement() should also contain a check that all elements inside the array are in fact strings. This prevents false matches in a oneOf schema declaration.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the generated Kotlin LocationDataTemperature.validateJsonElement() entry point and compare it with LocationDataWind.validateJsonElement(), especially the handling of the display array. Reproduce the Gradle Kotlin generation using the supplied schema and verify that string-array items are checked so the oneOf response does not match the wrong type.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin, openapi
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100