OpenAPITools / OpenAPITools/openapi-generator
[BUG] [java] nullable oneOf deserialization incorrect for isNullable
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 26.8k
- Forks
- 7.7k
- PR merge metrics
- PR metrics pending
Description
Bug Report Checklist
- Have you provided a full/minimal spec to reproduce the issue?
- Have you validated the input using an OpenAPI validator (example)?
- [] 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 using a nullable oneOf property, deserialization does not preserve the isNullable flag.
openapi-generator version
All versions since 7.5.0.
7.4.0 works correctly.
OpenAPI declaration file content or url
openapi: 3.0.3
info:
title: API
description: Hello
version: v1
servers:
- url: http://localhost:8080/
description: server url
tags:
- name: "Hello"
description: "The Hello resource"
paths:
/hello:
post:
tags:
- Hello
- FIDO
operationId: hello
summary: Returns a hello message.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/HelloRequest'
responses:
'200': # status code
description: Succeeded
content:
application/json:
schema:
$ref: '#/components/schemas/HelloResponse'
components:
schemas:
HelloRequest:
type: object
properties:
message:
type: string
minLength: 1
example: "friends"
optionalField:
type: integer
nullable: true
polymorphicProperties:
type: array
items:
$ref: '#/components/schemas/ParentProperty'
propertyOption:
$ref: '#/components/schemas/PropertyOption'
required:
- message
HelloResponse:
type: object
properties:
message:
type: string
example: "Hello friends"
ParentProperty:
type: object
discriminator:
propertyName: "propertyType"
properties:
parentValue:
type: string
ChildProperty1:
allOf:
- $ref: '#/components/schemas/ParentProperty'
- type: object
properties:
stringValue:
type: string
propertyType:
type: string
default: "ChildProperty1"
required:
- stringValue
ChildProperty2:
type: object
allOf:
- $ref: '#/components/schemas/ParentProperty'
- type: object
properties:
intValue:
type: integer
propertyType:
type: string
default: "ChildProperty2"
required:
- intValue
PropertyOption:
nullable: true
oneOf:
- $ref: '#/components/schemas/PropertyOption1'
- $ref: '#/components/schemas/PropertyOption2'
PropertyOption1:
type: object
properties:
stringValue:
type: string
required:
- stringValue
PropertyOption2:
type: object
properties:
intValue:
type: integer
required:
- intValue
Generation Details
I'm Using gradle plugin:
openApiGenerate {
generatorName = 'java'
additionalProperties = [
sourceFolder : "",
"annotationLibrary": "none",
"library" : "jersey2",
"performBeanValidation" : "true",
"useBeanValidation" : "true",
"useRuntimeException" : "true",
"hideGenerationTimestamp" : "true",
"useJakartaEe": "true"
]
}
Steps to reproduce
Generate Java models and perform a JSON round-trip of the DTO:
@Test
void request() throws JsonProcessingException {
HelloRequest initial = new HelloRequest()
.message("message")
.optionalField(15)
.polymorphicProperties(List.of(
new ChildProperty1()
.stringValue("stringValue"),
new ChildProperty2()
.intValue(10)))
.propertyOption(
new PropertyOption(
new PropertyOption2()
.intValue(15)));
String json = mapper.writeValueAsString(initial);
HelloRequest fromJson = mapper.readValue(json, HelloRequest.class);
assertThat(fromJson).isEqualTo(initial); // Fails because propertyOption.isNullable is true in fromJson
}
Related issues/PRs
Suggest a fix
The deserialization logic constructs an empty PropertyOption (using the default constructor which initializes isNullable to true) and then calls setActualInstance. So options I can see is either change isNullable in setActualnstance or change deserialization logic to use the constructor that takes the instance as an argument.
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 Java PropertyOption model and its deserialization path, especially the default constructor and setActualInstance mentioned in the report. Reproduce the Gradle-generated model round trip with the provided request test, then verify that deserialization preserves the original isNullable value and the equality assertion passes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, openapi
- Domain
- api, backend, testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100