Add support for resource inheritance in OpenAPI #1704
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR adds full OpenAPI support for resource inheritance in JSON:API.
Foundational changes
Component schema renames
To generate a universal set of schema/type names for JSON:API with and without resource inheritance, this PR applies the following renames. They affect the OpenAPI file and the type names of the generated code.
Hopefully, this is the final set of renames. It affects everyone who uses the pre-release versions; sorry for that.
Structural changes
The component schemas for the following request types now always have a shared abstract base type:
The resource type for resource data is now defined in a shared enumeration that lists all resource types, so there are no more resource-specific single-valued enumerations. This hasn't changed for resource identifiers.
Either way, these enumerations matter only to kiota users, who must specify the resource type explicitly. NSwag handles discriminator properties automatically and doesn't even expose them.
Resource inheritance
In short, there's a fundamental mismatch between the concept of inheritance in object-oriented design and composition in OpenAPI. NSwag overcomes that by breaking the inheritance chain in C#, while Kiota doesn't support it at all. See microsoft/kiota#5086 for the details.
To make it work in both tools, this PR introduces a JSON:API extension that allows sending an extra discriminator (which JsonApiDotNetCore ignores) in attributes, relationships and operations. This JSON:API OpenAPI extension is documented in
/docs/ext/openapi/index.md
. The extension is automatically activated when using theJsonApiDotNetCore.OpenApi.Swashbuckle
package. The package hooks into the JsonApiDotNetCore content negotiation and serializer to validate the extra discriminators on incoming JSON:API requests.Because of the above mismatch, clients must upcast attributes and relationships to access derived properties.
For example:
Unfortunately, this is unavoidable.
Implementation details
This PR improves the detection of unused component schemas in the output file. When tests run in DEBUG mode, they fail when unused component schemas appear in the OpenAPI output. It still does not detect types that only appear in discriminator mappings without being referenced elsewhere.
ResourceIdentifierSchemaGenerator
andAbstractResourceDataSchemaGenerator
got merged intoDataSchemaGenerator
.AbstractAtomicOperationSchemaGenerator
got merged intoAtomicOperationsBodySchemaGenerator
, which was renamed toAtomicOperationsDocumentSchemaGenerator
.DataSchemaGenerator
,DataContainerSchemaGenerator
andAtomicOperationsDocumentSchemaGenerator
were heavily refactored to support inheritance.SetSchemaTypeToObjectDocumentFilter
was added to workaround a bug in NSwag where it's unable to infer the proper schema type, resulting in invalid generated code.To workaround kiota bug microsoft/kiota#2432, the applicable discriminator mappings are repeated in every derived type in a type hierarchy (applies to types used in responses only).
An extensive suite of tests was added for several combinations with resource inheritance:
Closes #1457.
QUALITY CHECKLIST