diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute
index ef43ddd2..3452c1e2 100644
--- a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute
+++ b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute
@@ -85,6 +85,7 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if serializabl
/**
* Set {v.name}
**/
+ @JsonProperty("{v.baseName}")
public void {v.setter}({v.datatypeWithEnum} {v.name}) {
this.{v.name} = {v.name};
}
diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/pojoQueryParam.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/pojoQueryParam.qute
index 91612c3c..9db295c1 100644
--- a/client/deployment/src/main/resources/templates/libraries/microprofile/pojoQueryParam.qute
+++ b/client/deployment/src/main/resources/templates/libraries/microprofile/pojoQueryParam.qute
@@ -74,6 +74,7 @@
/**
* Set {v.name}
**/
+ @com.fasterxml.jackson.annotation.JsonProperty("{v.baseName}")
public void {v.setter}({v.datatypeWithEnum} {v.name}) {
this.{v.name} = {v.name};
}
diff --git a/client/integration-tests/jsonproperty-getter-and-setter/pom.xml b/client/integration-tests/jsonproperty-getter-and-setter/pom.xml
new file mode 100644
index 00000000..95232033
--- /dev/null
+++ b/client/integration-tests/jsonproperty-getter-and-setter/pom.xml
@@ -0,0 +1,93 @@
+
+
+
+ quarkus-openapi-generator-integration-tests
+ io.quarkiverse.openapi.generator
+ 3.0.0-SNAPSHOT
+
+ 4.0.0
+
+ quarkus-openapi-generator-it-jsonproperty-getter-and-setter
+ Quarkus - OpenAPI Generator - Integration Tests - Client - @JsonProperty for getters and setters
+ Ensures that @JsonProperty is properly added to getters and setters
+
+
+
+ io.quarkiverse.openapi.generator
+ quarkus-openapi-generator
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+
+
+
+ io.quarkus
+ quarkus-maven-plugin
+ true
+
+
+
+ build
+ generate-code
+ generate-code-tests
+
+
+
+
+
+
+
+
+ native-image
+
+
+ native
+
+
+
+
+
+ maven-surefire-plugin
+
+ ${native.surefire.skip}
+
+
+
+ maven-failsafe-plugin
+
+
+
+ integration-test
+ verify
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+
+ org.jboss.logmanager.LogManager
+
+ ${maven.home}
+
+
+
+
+
+
+
+
+ native
+
+
+
+
+
\ No newline at end of file
diff --git a/client/integration-tests/jsonproperty-getter-and-setter/src/main/openapi/jsonproperty-openapi.yaml b/client/integration-tests/jsonproperty-getter-and-setter/src/main/openapi/jsonproperty-openapi.yaml
new file mode 100644
index 00000000..b4977ab3
--- /dev/null
+++ b/client/integration-tests/jsonproperty-getter-and-setter/src/main/openapi/jsonproperty-openapi.yaml
@@ -0,0 +1,129 @@
+{
+ "openapi": "3.0.2",
+ "info": {
+ "title": "Animals - OpenAPI 3.0",
+ "version": "1.0.5"
+ },
+ "servers": [
+ {
+ "url": "/api/v3"
+ }
+ ],
+ "tags": [
+ {
+ "name": "primate",
+ "description": "Everything about Primates"
+ }
+ ],
+ "paths": {
+ "/primate/{id}": {
+ "get": {
+ "tags": [
+ "primate"
+ ],
+ "summary": "Find primate by ID",
+ "description": "Returns a single primate",
+ "operationId": "getPrimateById",
+ "parameters": [
+ {
+ "name": "id",
+ "in": "path",
+ "description": "ID of primate to return",
+ "required": true,
+ "schema": {
+ "type": "integer",
+ "format": "int64"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Primate"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid ID supplied"
+ },
+ "404": {
+ "description": "Primate not found"
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Animal": {
+ "type": "object",
+ "properties": {
+ "born": {
+ "type": "string",
+ "description": "Dated Base extension.",
+ "format": "date-time"
+ },
+ "deceased": {
+ "type": "string",
+ "description": "Dated Base extension.",
+ "format": "date-time"
+ },
+ "animal_name": {
+ "type": "string",
+ "description": "Animal name"
+ }
+ },
+ "xml": {
+ "name": "animal"
+ }
+ },
+ "Mammal": {
+ "type": "object",
+ "allOf": [ {
+ "$ref": "#/components/schemas/Animal"
+ } ],
+ "properties": {
+ "gender": {
+ "type": "string",
+ "enum": [
+ "female",
+ "male"
+ ]
+ }
+ },
+ "xml": {
+ "name": "mammal"
+ }
+ },
+ "Primate": {
+ "required": [
+ "name"
+ ],
+ "type": "object",
+ "allOf": [
+ {
+ "$ref": "#/components/schemas/Mammal"
+ }
+ ],
+ "properties": {
+ "id": {
+ "type": "integer",
+ "format": "int64",
+ "example": 10
+ },
+ "name": {
+ "type": "string",
+ "example": "jane doe"
+ }
+ },
+ "xml": {
+ "name": "primate"
+ }
+ }
+ }
+ }
+}
diff --git a/client/integration-tests/jsonproperty-getter-and-setter/src/main/resources/application.properties b/client/integration-tests/jsonproperty-getter-and-setter/src/main/resources/application.properties
new file mode 100644
index 00000000..964ab5d2
--- /dev/null
+++ b/client/integration-tests/jsonproperty-getter-and-setter/src/main/resources/application.properties
@@ -0,0 +1 @@
+quarkus.openapi-generator.codegen.spec.jsonproperty_openapi_yaml.base-package=org.acme.jsonproperty.gettersetter
\ No newline at end of file
diff --git a/client/integration-tests/jsonproperty-getter-and-setter/src/test/java/io/quarkiverse/openapi/generator/it/JsonPropertyGetterSetterTest.java b/client/integration-tests/jsonproperty-getter-and-setter/src/test/java/io/quarkiverse/openapi/generator/it/JsonPropertyGetterSetterTest.java
new file mode 100644
index 00000000..9759e675
--- /dev/null
+++ b/client/integration-tests/jsonproperty-getter-and-setter/src/test/java/io/quarkiverse/openapi/generator/it/JsonPropertyGetterSetterTest.java
@@ -0,0 +1,146 @@
+package io.quarkiverse.openapi.generator.it;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+
+import jakarta.json.Json;
+import jakarta.json.JsonObjectBuilder;
+
+import org.acme.jsonproperty.gettersetter.model.Animal;
+import org.acme.jsonproperty.gettersetter.model.Mammal;
+import org.acme.jsonproperty.gettersetter.model.Primate;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import io.quarkus.test.junit.QuarkusTest;
+
+@QuarkusTest
+class JsonPropertyGetterSetterTest {
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+ @BeforeAll
+ static void setup() {
+ OBJECT_MAPPER.findAndRegisterModules();
+ }
+
+ @Test
+ void verifyGetterSetterWorksOnSnakeCasedFields() {
+ JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
+ jsonObjectBuilder.add("animal_name", "Lion");
+
+ Animal animal;
+ try {
+ animal = OBJECT_MAPPER.readValue(jsonObjectBuilder.build().toString(), Animal.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ assertEquals(Animal.class, animal.getClass());
+ assertEquals("Lion", animal.getAnimalName());
+ }
+
+ @Test
+ void verifyGetterSetterWorksOnNonSnakeCasedFields() {
+ JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
+ // OffsetDateTime field to verify that non-snake-cased fields also work
+ jsonObjectBuilder.add("born", "2020-01-01T00:00:00Z");
+
+ Animal animal;
+ try {
+ animal = OBJECT_MAPPER.readValue(jsonObjectBuilder.build().toString(), Animal.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ assertEquals(Animal.class, animal.getClass());
+ DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendInstant().toFormatter();
+ assertEquals("2020-01-01T00:00:00Z", animal.getBorn().format(formatter));
+ }
+
+ @Test
+ void verifyJavaReflectionIndicatesJsonPropertyOnSettersAndGetters() {
+ try {
+ var getter = Animal.class.getMethod("getAnimalName");
+ var setter = Animal.class.getMethod("setAnimalName", String.class);
+
+ var getterAnnotation = getter.getAnnotation(JsonProperty.class);
+ var setterAnnotation = setter.getAnnotation(JsonProperty.class);
+
+ assertEquals("animal_name", getterAnnotation.value());
+ assertEquals("animal_name", setterAnnotation.value());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ try {
+ var getter = Primate.class.getMethod("getAnimalName");
+ var setter = Primate.class.getMethod("setAnimalName", String.class);
+
+ var getterAnnotation = getter.getAnnotation(JsonProperty.class);
+ var setterAnnotation = setter.getAnnotation(JsonProperty.class);
+
+ assertEquals("animal_name", getterAnnotation.value());
+ assertEquals("animal_name", setterAnnotation.value());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ try {
+ var getter = Mammal.class.getMethod("getAnimalName");
+ var setter = Mammal.class.getMethod("setAnimalName", String.class);
+
+ var getterAnnotation = getter.getAnnotation(JsonProperty.class);
+ var setterAnnotation = setter.getAnnotation(JsonProperty.class);
+
+ assertEquals("animal_name", getterAnnotation.value());
+ assertEquals("animal_name", setterAnnotation.value());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Test
+ void verifyJavaReflectionIndicatesJsonPropertyOnSettersAndGettersQueryParam() {
+ try {
+ var getter = Animal.AnimalQueryParam.class.getMethod("getAnimalName");
+ var setter = Animal.AnimalQueryParam.class.getMethod("setAnimalName", String.class);
+
+ var getterAnnotation = getter.getAnnotation(JsonProperty.class);
+ var setterAnnotation = setter.getAnnotation(JsonProperty.class);
+
+ assertEquals("animal_name", getterAnnotation.value());
+ assertEquals("animal_name", setterAnnotation.value());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+
+ try {
+ var getter = Mammal.MammalQueryParam.class.getMethod("getAnimalName");
+ var setter = Mammal.MammalQueryParam.class.getMethod("setAnimalName", String.class);
+
+ var getterAnnotation = getter.getAnnotation(JsonProperty.class);
+ var setterAnnotation = setter.getAnnotation(JsonProperty.class);
+
+ assertEquals("animal_name", getterAnnotation.value());
+ assertEquals("animal_name", setterAnnotation.value());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+
+ try {
+ var getter = Primate.PrimateQueryParam.class.getMethod("getAnimalName");
+ var setter = Primate.PrimateQueryParam.class.getMethod("setAnimalName", String.class);
+
+ var getterAnnotation = getter.getAnnotation(JsonProperty.class);
+ var setterAnnotation = setter.getAnnotation(JsonProperty.class);
+
+ assertEquals("animal_name", getterAnnotation.value());
+ assertEquals("animal_name", setterAnnotation.value());
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/client/integration-tests/pom.xml b/client/integration-tests/pom.xml
index 2a5f0cd0..e66a541d 100644
--- a/client/integration-tests/pom.xml
+++ b/client/integration-tests/pom.xml
@@ -49,6 +49,7 @@
serializable-model
equals-hashcode
override-credential-provider
+ jsonproperty-getter-and-setter