openapi-generator: [BUG] Inheritance is broken
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator (example)?
- What’s the version of OpenAPI Generator used?
- Have you search for related issues/PRs?
- What’s the actual output vs expected output?
Description
Basic inheritance, as described in the OpenAPI spec does not work.
Instead of creating a class / interface hierarchy using inheritance to represent the composition, all properties are flattened into the subclass.
openapi-generator version
4.0.0-20190508.072036-627 or master
OpenAPI declaration file content or url
schema.yaml:
openapi: "3.0.1"
info:
version: 1.0.0
title: Inheritance test
paths:
/order:
get:
summary: Product order details
operationId: getOrder
responses:
'500':
description: Successful load
content:
application/json:
schema:
$ref: '#/components/schemas/ExtendedErrorModel'
components:
schemas:
BasicErrorModel:
type: object
required:
- message
- code
properties:
message:
type: string
code:
type: integer
minimum: 100
maximum: 600
ExtendedErrorModel:
allOf:
- $ref: '#/components/schemas/BasicErrorModel'
- type: object
required:
- rootCause
properties:
rootCause:
type: string
Expected output
The following class/interface hierarchy: to be generated:
BasicErrorModel<-ExtendedErrorModel
Actual output
Three unrelated classes/interfaces:
BasicErrorModelExtendedErrorModelExtendedErrorModelAllOf
Command line used for generation
java -jar openapi-generator-cli.jar generate -i ./schema.yaml -g typescript-angular -o src
I have also tried with the Java generator, and it creates the same hierarchy, so it is not just a Typescript problem.
Steps to reproduce
- Copy the above yaml into
schema.yamllocally. - Run the command above.
- Examine the generated code.
Suggest a fix
I’m not familiar with the codebase, but it appears that getParentName in ModelUtils.java only considers a class as a viable parent for inheritance if it has a discriminator, but the above inheritance pattern does not use discriminators.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 26
- Comments: 87 (41 by maintainers)
Links to this issue
Commits related to this issue
- issue #2845: run ./bin/openapi3/typescript-angular-petstore-all.sh — committed to mnahkies/openapi-generator by mnahkies 5 years ago
- issue #2845: enable 'supportsMultipleInheritance' on typescript angular client codegen - note I reran ./bin/openapi3/typescript-angular-petstore-all.sh and no changes occurred. this suggests to me ... — committed to mnahkies/openapi-generator by mnahkies 5 years ago
- issue #2845: run ./bin/openapi3/typescript-angular-petstore-all.sh — committed to mnahkies/openapi-generator by mnahkies 5 years ago
- issue #2845: enable 'supportsMultipleInheritance' on typescript angular client codegen - note I reran ./bin/openapi3/typescript-angular-petstore-all.sh and no changes occurred. this suggests to me ... — committed to mnahkies/openapi-generator by mnahkies 5 years ago
- Bug #2845 typescript angular inheritance (#3812) * issue #2845: enable 'supportsMultipleInheritance' on typescript angular client codegen - note I reran ./bin/openapi3/typescript-angular-petstore-... — committed to OpenAPITools/openapi-generator by mnahkies 5 years ago
- Bug #2845 typescript angular inheritance (#3812) * issue #2845: enable 'supportsMultipleInheritance' on typescript angular client codegen - note I reran ./bin/openapi3/typescript-angular-petstore-... — committed to hokamoto/openapi-generator by mnahkies 5 years ago
- Add Nim client code generator (#3879) * First version of Nim Client * Add some codes * Add some codes * Add some codes * Add some codes * Add some codes * First version of Nim Clien... — committed to OpenAPITools/openapi-generator by hokamoto 5 years ago
Enough people have commented on this. The old behavior is what we expect. Not the fixed one.
Inheritance via allOf (what we want) isn’t the same as polymorphic serialization (what discriminator does). Could we at least have an option to restore the previous behavior that worked for a lot of people?
@wing328 The discriminator is intended to tell API consumers how they can polymorphically distinguish the type of an incoming object, it doesn’t imply that a code generator must flatten any relationship without a discriminator in order to represent the composition.
At the very least, this decision should be left up to the language-specific generator rather than being made prematurely in the default codegen. TypeScript for example has absolutely no problem representing this kind of discriminator-less composition via interfaces, which do not imply any kind of runtime inheritance hierarchy, but allow for types to represent an extension/composition of one or more parent types.
And, indeed, this is exactly how the current release of openapi-generator works!
Run the example I provided through the release available in homebrew, and you will get an interface
ExtendedErrorModelthat inherits from an interfaceBasicErrorModel, exactly as you would expect. It is only with the current snapshot that you get these three, unrelated interfaces:BasicErrorModelExtendedErrorModelExtendedErrorModelAllOfThis is just not right, and is happening because
DefaultCodegenis prematurely deciding to throw away the child-parent relationship expressed by the allOf, perhaps based on the incorrect assumption that Java-style class hierarchies are the only type of extension mechanism in existence?See also this inheritance example, again taken directly from the OpenAPI docs:
The code generated for this spec is broken and unusable.
@loicdesguin @palufra90 I think some of the indentation is wrong. I got it to work with this:
to
Notice how
allOfandtype: objecthave to be at the same level for this to work!Tested on 4.3.1 with
typescript-axios.I am seeing the same issues for the test files in the project. These generate broken code:
Etc.
How on Earth is the project passing all its tests when the output is this state?
EDIT: I see now that the
petstore.yamlthat is being used to regression test every generator doesn’t contain any use ofanyOf,allOf,oneOf, discriminators, etc. There’s no way you can catch issues with these features, even when they’re massively broken, like now.@macjohnny thanks for bringing it to my attention. I definitely want to take another look at the issue as I thought
discriminatorshould setup the model inheritance properly but @Patre suggested otherwise in https://github.com/OpenAPITools/openapi-generator/issues/2845#issuecomment-493863254.However I’m very busy as usual and I’ll try to look into it again after the Open Summit Japan 2019 next week.
If anyone wants to help on the issue, please feel free to submit a PR to start with.
@wing328 You don’t appear to be even trying to read or understand what I’m writing, so I don’t see much point in continuing this.
It seems that there are quite a few issues open about this:
I solved the inheritance problem for the typescript/angular generator indenting the property object with the ref object. From
to
In this way the generated typescript interface is
So why is this closed?
In our project we had to temporarily switch to another Gradle plugin ‘org.hidetake.swagger.generator’ which works well with Gradle 5 and allows downgrading open-api generator to 3.3.4(org.openapitools:openapi-generator-cli:3.3.4). And 3.3.4 properly handles inheritance, so if you need it(inheritance i mean), then you definitely have to somehow use this particular version
Is there a previous version I can rollback to so I can get
extendsback?@wing328 could you have a look at this one again? I think this is a regression since it used to work correctly
@wing328 This is not about enhancing generators, it’s an issue of fixing
DefaultCodegen.javato create the models correctly in the first place. The changes made to support multiple inheritance and OA3 appear to have made the situation worse, not better. For example, basic Swagger 2.0allOfaggregation works in the current release version, but is broken in the snapshot, because the code for resolving parents now only understands discriminator-based parent relationships. If 4.0 is released as-is, it is going to break with a lot of specs that previously worked.There should have been a comprehensive regression test for what aggregation was supported before the attempts to implement OA3 began, to ensure those changes didn’t break anything. As things stand, the codebase is already broken WRT inheritance, so the task now is to both implement a comprehensive regression test while simultaneously fixing the default codegen. I’m happy to try to help with this, but it’s going to take me a while to understand everything that’s happening in
DefaultCodegen.java.Any update on this?
I cannot manage to get inheritance when generating client for dart
Same here, just upgraded to the latest version 4, and interfaces generated with
typescript-angularno longer extend other interfaces when usingallOfwithoutdiscriminator. I understand that this seems to be correct according to the spec:But: This is a breaking change. IMHO, at the very least it should be pointed out / documented, at best we’d have a fallback option as @lemoinem suggested.
I think I have the same error that
allOfis not supprted correctly. I use a derived type as request body. I´m using maven generator “java” with different libraries - native, retrofit , …4.3.0-SNAPSHOTThe class
UserCreateis created with all fields fromUserUpdateand thesend_welcome_emailproperty - but the method has no argument.So why is this issue marked as closed? Please reopen…
Hod do you guys set
supportsMultipleInheritance/supportsInheritancefortypescript-angulargenerator? I did try--additional-properties supportsMultipleInheritance/supportsInheritance=truewith no success. There is also no mention about such a parametres in here: https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators/typescript-angular.md Thanks.Ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#composition-and-inheritance-polymorphism
I’m afraid we’ve to stick with the definitions defined in the specification.
In your case, why not update the OpenAPI documents to use the discriminator field?
@jonrimmer I read your issue report again and notice there may be an incorrect interpretation of
allOf(composition vs inheritance).In the example you provided,
BasicErrorModeldoes not containdiscriminator(example) so model composition is used insteadRef:
@jonrimmer you are right, there should be some more tests. would you like to give a hand? cc @wing328
I have no issues with the spec other than that I fail to understand what should be a discriminator in this case:
schema
But that’s OK, I can live with composition in TypeScript case. The problem I have is that I see no way to distinguish own properties and those pulled from
refin templates.isInheritedflag is not set and there is noisMixedInflag. In the example above this makes the generator create 2 separatetagsenums which leads toCategoryandCategoryWithRelationsbeing not compatible TypeScript types.typescript-fetchgenerator is also broken in 4.3.1 Inheritance without a discriminator works perfectly fine in 4.3.0. In 4.3.1 a subclass gets all the properties of a superclass instead of inheritance and an extra class namedSubclassAllOfis generated. @wing328 Please reopen this@lacksfish @jonrimmer Following the advice to leverage the incredible https://github.com/APIDevTools/json-schema-ref-parser tool, I threw together a little script that does a hybrid de-reference of the openapi schemas (models). This way, you can still keep the non-inheritance/polymorphism-related references (for example, properties of an object that just reference another defined object), but still collapse any
allOfreferences in a model.I hope it helps you guys.
This getting
UNKNOWN_BASE_TYPE UNKNOWN_BASE_TYPEwith spring-boot generator for the Cat Dog example above@bricox I think we’ve only added better anyOf support (beta) to the Ruby client generator. We welcome contributions to make similar enhancements to other generators.
I retested with the current version and the generated files are working fine with discriminator inheritance (elm and java/springboot).
For both languages there are additional files generated with an
AllOfsuffix that weren’t before. (MessageAllOf.elm/MessageAllOf.java). Not an issue, but I noticed it as a difference.Thanks to everybody who took a look at the issue 😃
We just started adding better support for allOf, anyOf, oneOf to different generators and I foresee it will take a while for all generators to support these new features in OAS v3.
If you or anyone wants to help with the implementation of these new features in any generators, let me know and I’ll show you some good starting points.