Bug Report Checklist
Description
given an optioal array with 'minItems: 1', fails validation if this array isn't provided by the client.
All arrays defined in OpenAPI are, by default, initialized as empty lists in Java. If an array is required to have at least one entry when it is provided, validation will fail if the client omits the array.
openapi-generator version
v7.18.0, v7.19.0, master
OpenAPI declaration file content or url
OpenApi declaration:
openapi: 3.1.1
info:
title: Optional Array OpenAPI Example
version: 1.0.0
paths:
/v1/new-customer:
put:
operationId: setNewCustomer
requestBody:
description: the new customer to be created
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NewCustomerRequest'
responses:
204:
description: The new customer was set successfully.
components:
schemas:
NewCustomerRequest:
type: object
properties:
newCustomer:
properties:
name:
type: string
required:
- name
documents:
description: |
the documents to be attached to identify the new customer.
This array is optional. If provided, it must contain between 1 and 3 items
type: array
items:
$ref: '#/components/schemas/Document'
minItems: 1
maxItems: 3
required:
- newCustomer
Document:
type: object
properties:
documentId:
description: |
The document id (uuid)
type: string
format: uuid
documentType:
$ref: '#/components/schemas/DocumentType'
documentNo:
type: string
required:
- documentId
- documentType
- documentNo
DocumentType:
type: string
enum:
- ID_CARD
- PASSPORT
Generation Details
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate
-i optional_array-openapi.yaml
-g spring
-o tmp/spring-api
generates this model:
package org.openapitools.model;
import java.net.URI;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonCreator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.openapitools.model.Document;
import org.openapitools.model.NewCustomerRequestNewCustomer;
import org.springframework.lang.Nullable;
import org.openapitools.jackson.nullable.JsonNullable;
import java.time.OffsetDateTime;
import javax.validation.Valid;
import javax.validation.constraints.*;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.*;
import javax.annotation.Generated;
/**
* NewCustomerRequest
*/
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2026-01-23T09:37:18.269659+01:00[Europe/Zurich]", comments = "Generator version: 7.20.0-SNAPSHOT")
public class NewCustomerRequest {
private NewCustomerRequestNewCustomer newCustomer;
@Valid
private List<@Valid Document> documents = new ArrayList<>();
public NewCustomerRequest() {
super();
}
/**
* Constructor with only required parameters
*/
public NewCustomerRequest(NewCustomerRequestNewCustomer newCustomer) {
this.newCustomer = newCustomer;
}
public NewCustomerRequest newCustomer(NewCustomerRequestNewCustomer newCustomer) {
this.newCustomer = newCustomer;
return this;
}
/**
* Get newCustomer
* @return newCustomer
*/
@NotNull @Valid
@Schema(name = "newCustomer", requiredMode = Schema.RequiredMode.REQUIRED)
@JsonProperty("newCustomer")
public NewCustomerRequestNewCustomer getNewCustomer() {
return newCustomer;
}
public void setNewCustomer(NewCustomerRequestNewCustomer newCustomer) {
this.newCustomer = newCustomer;
}
public NewCustomerRequest documents(List<@Valid Document> documents) {
this.documents = documents;
return this;
}
public NewCustomerRequest addDocumentsItem(Document documentsItem) {
if (this.documents == null) {
this.documents = new ArrayList<>();
}
this.documents.add(documentsItem);
return this;
}
/**
* the documents to be attached to identify the new customer. This array is optional. If provided, it must contain between 1 and 3 items
* @return documents
*/
@Valid @Size(min = 1, max = 3)
@Schema(name = "documents", description = "the documents to be attached to identify the new customer. This array is optional. If provided, it must contain between 1 and 3 items ", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@JsonProperty("documents")
public List<@Valid Document> getDocuments() {
return documents;
}
public void setDocuments(List<@Valid Document> documents) {
this.documents = documents;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
NewCustomerRequest newCustomerRequest = (NewCustomerRequest) o;
return Objects.equals(this.newCustomer, newCustomerRequest.newCustomer) &&
Objects.equals(this.documents, newCustomerRequest.documents);
}
@Override
public int hashCode() {
return Objects.hash(newCustomer, documents);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class NewCustomerRequest {\n");
sb.append(" newCustomer: ").append(toIndentedString(newCustomer)).append("\n");
sb.append(" documents: ").append(toIndentedString(documents)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(@Nullable Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
Steps to reproduce
given the declaration above, generate the java code and execute this test:
package org.openapitools.model;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
public class NewCustomerRequestTest {
private final Validator validator;
public NewCustomerRequestTest() {
try (ValidatorFactory factory = Validation.buildDefaultValidatorFactory()) {
this.validator = factory.getValidator();
}
}
@Test
void testNewCustomerReadFromJsonAndValidate()
throws Exception {
final String newCustomerJsonString = "{\"newCustomer\":{\"name\":\"test customer name\"}}";
final NewCustomerRequest newCustomer = new ObjectMapper().readValue(newCustomerJsonString, NewCustomerRequest.class);
final Set<ConstraintViolation<NewCustomerRequest>> newCustomerValidations = validator.validate(newCustomer);
assertThat(newCustomerValidations).isEmpty();
}
}
Related issues/PRs
#18735
#21269
Suggest a fix
The generator must check whether an array has 'minItems' defined and whether it is optional. If so, the array must not be initialized by default in Java.
Bug Report Checklist
Description
given an optioal array with 'minItems: 1', fails validation if this array isn't provided by the client.
All arrays defined in OpenAPI are, by default, initialized as empty lists in Java. If an array is required to have at least one entry when it is provided, validation will fail if the client omits the array.
openapi-generator version
v7.18.0, v7.19.0, master
OpenAPI declaration file content or url
OpenApi declaration:
Generation Details
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate
-i optional_array-openapi.yaml
-g spring
-o tmp/spring-api
generates this model:
Steps to reproduce
given the declaration above, generate the java code and execute this test:
Related issues/PRs
#18735
#21269
Suggest a fix
The generator must check whether an array has 'minItems' defined and whether it is optional. If so, the array must not be initialized by default in Java.