-
-
Notifications
You must be signed in to change notification settings - Fork 7.4k
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
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
- PASSPORTGeneration 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
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.