Bug Report Checklist
Description
Hi,
I tried to plug in a custom jackson.JsonDeserialize for a property with type: array and uniqueItems: true in a component schema, but it didn't work as I expected. A few moments later with a debugger I discovered that there's no way at the moment to achieve a custom deserialization in Java for Set collection at codegen, and the reason is that jackson has a JsonDeserialize priority of x-setter-extra-annotation over x-field-extra-annotation.
My custom JsonDeserialize:
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.apache.commons.lang3.StringUtils;
public class TrimmingStringSetDeserializer extends StdDeserializer<Set<String>> {
protected TrimmingStringSetDeserializer() {
super(Set.class);
}
@Override
public Set<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
if (p.getCurrentToken() == JsonToken.START_ARRAY) {
Set<String> values = new HashSet<>();
while (p.nextToken() != JsonToken.END_ARRAY) {
String value = StringUtils.trimToNull(p.getValueAsString());
if (value != null) {
values.add(value);
}
}
return values;
}
ctxt.reportWrongTokenException(Set.class, JsonToken.START_ARRAY, "Expected string set");
throw new RuntimeException("reportWrongTokenException");
}
}
The way I was expected it to work:
properties:
nicknames:
type: array
uniqueItems: true
# x-field-extra-annotation: '@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = org.openapitools.tools.TrimmingStringSetDeserializer.class)'
x-setter-extra-annotation: '@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = org.openapitools.tools.TrimmingStringSetDeserializer.class)'
items:
type: string
The way java codegen works at the moment:
// always sets as a default
@JsonDeserialize(as = LinkedHashSet.class)
@JsonProperty("nicknames")
public void setNicknames(Set<String> nicknames) {
this.nicknames = nicknames;
}
If x-field-extra-annotation is custom, it's always ignored, and for x-setter-extra-annotation it's simply not working because of the default codegen.
openapi-generator version
latest
OpenAPI declaration file content or url
openapi: 3.0.0
info:
title: API
version: 1.0.0
paths:
/pet:
post:
summary: Add a new pet to the store
operationId: addPet
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
responses:
'200':
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
components:
schemas:
Pet:
title: a Pet
description: A pet for sale in the pet store
properties:
nicknames:
type: array
uniqueItems: true
# x-field-extra-annotation: '@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = org.openapitools.tools.TrimmingStringSetDeserializer.class)'
x-setter-extra-annotation: '@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = org.openapitools.tools.TrimmingStringSetDeserializer.class)'
items:
type: string
Generation Details
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 com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.lang.Nullable;
import org.openapitools.jackson.nullable.JsonNullable;
import java.time.OffsetDateTime;
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.*;
import jakarta.annotation.Generated;
/**
* A pet for sale in the pet store
*/
@Schema(name = "Pet", description = "A pet for sale in the pet store")
@Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2026-04-13T10:23:49.058908+03:00[Europe/Moscow]", comments = "Generator version: unset")
public class Pet {
@Valid
private Set<String> nicknames = new LinkedHashSet<>();
public Pet nicknames(Set<String> nicknames) {
this.nicknames = nicknames;
return this;
}
public Pet addNicknamesItem(String nicknamesItem) {
if (this.nicknames == null) {
this.nicknames = new LinkedHashSet<>();
}
this.nicknames.add(nicknamesItem);
return this;
}
/**
* Get nicknames
* @return nicknames
*/
@Schema(name = "nicknames", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@JsonProperty("nicknames")
public Set<String> getNicknames() {
return nicknames;
}
@JsonDeserialize(as = LinkedHashSet.class)
@JsonProperty("nicknames")
public void setNicknames(Set<String> nicknames) {
this.nicknames = nicknames;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Pet pet = (Pet) o;
return Objects.equals(this.nicknames, pet.nicknames);
}
@Override
public int hashCode() {
return Objects.hash(nicknames);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class Pet {\n");
sb.append(" nicknames: ").append(toIndentedString(nicknames)).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) {
return o == null ? "null" : o.toString().replace("\n", "\n ");
}
}
Steps to reproduce
- Clone the repository
- Set up locally openapi schema as I mentioned above
- Pass to
org.openapitools.codegen.OpenAPIGenerator arguments generate -g spring -i "/Users/<user>/Library/Application Support/JetBrains/IntelliJIdea2025.3/scratches/scratch_22.yml" -o ./out/generated-java-openapi
- Look at
org.openapitools.model.Pet#setNicknames
Related issues/PRs
Didn't find an appropriate one.
Suggest a fix
[Java] [Spring] Support a custom declaration of x-setter-extra-annotation at codegen for unique arrays#23522
Bug Report Checklist
Description
Hi,
I tried to plug in a custom jackson.JsonDeserialize for a property with
type: arrayanduniqueItems: truein a component schema, but it didn't work as I expected. A few moments later with a debugger I discovered that there's no way at the moment to achieve a custom deserialization in Java for Set collection at codegen, and the reason is that jackson has a JsonDeserialize priority ofx-setter-extra-annotationoverx-field-extra-annotation.My custom JsonDeserialize:
The way I was expected it to work:
The way java codegen works at the moment:
If
x-field-extra-annotationis custom, it's always ignored, and forx-setter-extra-annotationit's simply not working because of the default codegen.openapi-generator version
latest
OpenAPI declaration file content or url
Generation Details
Steps to reproduce
org.openapitools.codegen.OpenAPIGeneratorargumentsgenerate -g spring -i "/Users/<user>/Library/Application Support/JetBrains/IntelliJIdea2025.3/scratches/scratch_22.yml" -o ./out/generated-java-openapiorg.openapitools.model.Pet#setNicknamesRelated issues/PRs
Didn't find an appropriate one.
Suggest a fix
[Java] [Spring] Support a custom declaration of x-setter-extra-annotation at codegen for unique arrays#23522