-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Open
Labels
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator?
- Have you tested with the latest master to confirm the issue still exists?
- Have you searched for related issues/PRs?
- What's the actual output vs expected output?
- [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description
When having an endpoint that returns R being oneOf a or b (or more), the generated classes for A and B do not implement the generated interface which is generated for R and therefore the deserialization with Jackson fails.
openapi-generator version
7.14.0 (gradle plugin)
OpenAPI declaration file content or url
---
openapi: 3.0.1
info:
title: some
version: 1.0.0
servers:
- url: http://localhost:8080
description: Local server
paths:
"/someEndponint":
get:
summary: Get the specified device job of a single device
description: |
Obtain a specified device job of a single device
operationId: someEndpoint
responses:
'200':
description: Success
content:
application/json:
schema:
oneOf:
- "$ref": "#/components/schemas/A"
- "$ref": "#/components/schemas/B"
discriminator:
propertyName: jobType
mapping:
A: "#/components/schemas/A"
B: "#/components/schemas/B"
components:
schemas:
A:
type: object
properties:
jobType:
type: string
propertyA:
type: string
B:
type: object
properties:
jobType:
type: string
propertyB:
type: string
Generation Details
here is the plugin configuration:
tasks.register<GenerateTask>("openApiGenerateV2Client") {
generatorName = "kotlin"
inputSpec = "$projectDir/src/main/resources/static/v2/open-api-docs.yaml"
outputDir = "${layout.buildDirectory.get()}/generated/client/"
configOptions =
mapOf(
"library" to "jvm-spring-restclient",
"serializationLibrary" to "jackson",
"useSpringBoot3" to "true",
)
}Steps to reproduce
have a server that implement specified interface, call the client method, it produces the following Exception:
Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'A' as a subtype of `...SomeEndpoint200Response`: Class `...A` not subtype of `...SomeEndpoint200Response`
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 12]
at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
at com.fasterxml.jackson.databind.DeserializationContext.invalidTypeIdException(DeserializationContext.java:2096)
at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._findDeserializer(TypeDeserializerBase.java:198)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:150)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:135)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:262)
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:74)
at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:342)
Here the generated Code
data class A (
@get:JsonProperty("jobType")
val jobType: kotlin.String? = null,
@get:JsonProperty("propertyA")
val propertyA: kotlin.String? = null
)
data class B (
@get:JsonProperty("jobType")
val jobType: kotlin.String? = null,
@get:JsonProperty("propertyB")
val propertyB: kotlin.String? = null
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "jobType", visible = true)
@JsonSubTypes(
)
interface SomeEndpoint200Response {
@get:JsonProperty("jobType")
val jobType: kotlin.String?
@get:JsonProperty("propertyA")
val propertyA: kotlin.String?
@get:JsonProperty("propertyB")
val propertyB: kotlin.String?
}Related issues/PRs
Suggest a fix
How the code should be generated (note, the Java generator creates a similar structure):
data class A : SomeEndpoint200Response (
@get:JsonProperty("jobType")
override val jobType: kotlin.String? = null,
@get:JsonProperty("propertyA")
val propertyA: kotlin.String? = null
)
data class B : SomeEndpoint200Response (
@get:JsonProperty("jobType")
override val jobType: kotlin.String? = null,
@get:JsonProperty("propertyB")
val propertyB: kotlin.String? = null
)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "jobType", visible = true)
@JsonSubTypes(
)
interface SomeEndpoint200Response {
@get:JsonProperty("jobType")
val jobType: kotlin.String?
}m-barnas