Open sky-andremartins opened 2 years ago
I have the same problem so I did some debugging. These are my initial thoughts.
The relevant code is DefaultCodegen.toInstantiationType which does not recursively build the generic arguments as is done in AbstractKotlinCodegen.getTypeDeclaration.
A simple code fix for this would be (see inline comments for added parts):
public String toInstantiationType(Schema schema) {
if (ModelUtils.isMapSchema(schema)) {
Schema additionalProperties = getAdditionalProperties(schema);
String inner;
if (ModelUtils.isArraySchema(additionalProperties)) {
// recursive step to get generic arguments for the List
inner = toInstantiationType(additionalProperties);
} else {
// inner type is not a List, no need for recursion
inner = getSchemaType(additionalProperties);
}
return instantiationTypes.get("map") + "<String, " + inner + ">";
} else if (ModelUtils.isArraySchema(schema)) {
ArraySchema arraySchema = (ArraySchema) schema;
String inner = getSchemaType(getSchemaItems(arraySchema));
String parentType;
if (ModelUtils.isSet(schema)) {
parentType = "set";
} else {
parentType = "array";
}
return instantiationTypes.get(parentType) + "<" + inner + ">";
} else {
return null;
}
}
It's not flexible for other inner types but it solves this specific case and generates perfectly valid code like this:
data class Item(val id: String, val type: String)
class Responses (
) : kotlin.collections.HashMap<String, kotlin.collections.List<Item>>()
But I have trouble using it in my app because I cannot cast a HashMap
to the generated model class Responses
:
class java.util.HashMap cannot be cast to class com.etc.Responses (java.util.HashMap is in module java.base of loader 'bootstrap'; com.etc.Responses is in unnamed module of loader 'app')
(edited to use your example)
A fundamental problem here is that generating the alias using inheritance requires instantiation types (HashMap
, ArrayList
) (which is what the code generator does) because otherwise the generated model classes would have to implement the interface types (Map
, List
).
But anyway I don't fully understand what's going on with the loaders, so I am wondering if it would be better if the "generate alias as model" option simply generated:
data class Item(val id: String, val type: String)
typealias Responses = Map<String, List<Item>>
Advantages of this approach:
Disadvantages:
Issue still exists in latest 6.2.0 version. It is problematic because I needed use .openapi-generator-ignore file and ignore some types during generating and later build it manually.
this affects jax-rs spec as well, so I'm guessing the problem is not limited to kotlin, so please don't just fix it there
Giving my +1 to this. I have an API endpoint that returns a Map<String, List<MyObject>>
, and unfortunately the python code generated ends up saying Dict[str, object]
Bug Report Checklist
Description
When trying to specify additional properties to handle dynamic keys which will always be an array of a certain type, the generator doesn't specify the List's type correctly.
For the declaration below it generates model as following:
Which is incorrect as the expected one would be something like this:
openapi-generator version
Gradle plugin
5.4.0
OpenAPI declaration file content or url
Generation Details
Gradle generator task config
Steps to reproduce
Generate the models using the above described spec
Related issues/PRs
NA
Suggest a fix
NA