Merge pull request #744 from KyleAure/347-jsonbCreator-priority
test: verify how yasson behaves in regard to TCK challenge
diff --git a/src/test/java/org/eclipse/yasson/customization/JsonbCreatorTest.java b/src/test/java/org/eclipse/yasson/customization/JsonbCreatorTest.java
index de4c44a..1e1715c 100644
--- a/src/test/java/org/eclipse/yasson/customization/JsonbCreatorTest.java
+++ b/src/test/java/org/eclipse/yasson/customization/JsonbCreatorTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2026 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -24,8 +24,13 @@
import org.eclipse.yasson.customization.model.CreatorConstructorPojo;
import org.eclipse.yasson.customization.model.CreatorFactoryMethodPojo;
+import org.eclipse.yasson.customization.model.CreatorConstructorSetterConflicts;
+import org.eclipse.yasson.customization.model.CreatorFactoryNameConflicts;
+import org.eclipse.yasson.customization.model.CreatorFactorySetterConflicts;
import org.eclipse.yasson.customization.model.CreatorIncompatibleTypePojo;
+import org.eclipse.yasson.customization.model.CreatorIncompleteParameters;
import org.eclipse.yasson.customization.model.CreatorMultipleDeclarationErrorPojo;
+import org.eclipse.yasson.customization.model.CreatorNameConflicts;
import org.eclipse.yasson.customization.model.CreatorPackagePrivateConstructor;
import org.eclipse.yasson.customization.model.CreatorWithoutJavabeanProperty;
import org.eclipse.yasson.customization.model.CreatorWithoutJsonbProperty1;
@@ -156,6 +161,49 @@
}
@Test
+ public void testFactoryCreatorNameConflicts() {
+ String json = "{\"value\":\"hello\"}";
+ CreatorFactoryNameConflicts result = defaultJsonb.fromJson(json, CreatorFactoryNameConflicts.class);
+ assertNull(result.value, "value should have been claimed by the factory method parameter, not set on the field.");
+ assertEquals("HELLO", result.creatorValue, "value should have been routed to creatorValue via the factory method.");
+ }
+
+ @Test
+ public void testConstructorCreatorSetterConflicts() {
+ String json = "{\"value\":\"hello\"}";
+ CreatorConstructorSetterConflicts result = defaultJsonb.fromJson(json, CreatorConstructorSetterConflicts.class);
+ assertNull(result.getValue(), "value should have been claimed by the constructor parameter, not set via the setter.");
+ assertEquals("HELLO", result.creatorValue, "value should have been routed to creatorValue via the constructor.");
+ }
+
+ @Test
+ public void testFactoryCreatorSetterConflicts() {
+ String json = "{\"value\":\"hello\"}";
+ CreatorFactorySetterConflicts result = defaultJsonb.fromJson(json, CreatorFactorySetterConflicts.class);
+ assertNull(result.getValue(), "value should have been claimed by the factory method parameter, not set via the setter.");
+ assertEquals("HELLO", result.creatorValue, "value should have been routed to creatorValue via the factory method.");
+ }
+
+ @Test
+ public void testCreatorNameConflicts() {
+ String json = "{\"fromJson\":\"jsonValue\"}";
+ CreatorNameConflicts result = defaultJsonb.fromJson(json, CreatorNameConflicts.class);
+ assertNull(result.fromJson, "fromJson should have been routed to fromCreator using the @JsonbProperty annotation on the constructor parameter.");
+ assertEquals("JSONVALUE", result.fromCreator, "fromJson should have been routed to fromCreator using the @JsonbProperty annotation on the constructor parameter.");
+ assertNull(result.notProvided, "notProvided was not provided in the JSON, so it should be null.");
+ assertEquals(0, result.notDeclared, "notDeclared should have been set to a default value.");
+ }
+
+ @Test
+ public void testCreatorPassthroughFields() {
+ String json = "{\"declaredField\":\"declaredValue\", \"notDeclaredField\":\"notDeclaredValue\", \"notDeclaredSetter\":\"notDeclaredSetterValue\"}";
+ CreatorIncompleteParameters result = defaultJsonb.fromJson(json, CreatorIncompleteParameters.class);
+ assertEquals("DECLAREDVALUE", result.declaredField, "declaredField should have been set from the @JsonbCreator.");
+ assertEquals("notDeclaredValue", result.notDeclaredField, "notDeclaredField should have been set via the normal deserialization pathway.");
+ assertEquals("notDeclaredSetterValue", result.getNotDeclaredSetter(), "notDeclaredSetter should have been set via the normal deserialization pathway.");
+ }
+
+ @Test
public void testGenericCreatorParameter() throws Exception {
final String json = "{\"persons\": [{\"name\": \"name1\"}]}";
Persons persons = defaultJsonb.fromJson(json, Persons.class);
diff --git a/src/test/java/org/eclipse/yasson/customization/model/CreatorConstructorSetterConflicts.java b/src/test/java/org/eclipse/yasson/customization/model/CreatorConstructorSetterConflicts.java
new file mode 100644
index 0000000..40a257d
--- /dev/null
+++ b/src/test/java/org/eclipse/yasson/customization/model/CreatorConstructorSetterConflicts.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2026 Eclipse and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+package org.eclipse.yasson.customization.model;
+
+import java.util.Locale;
+
+import jakarta.json.bind.annotation.JsonbCreator;
+import jakarta.json.bind.annotation.JsonbProperty;
+
+/**
+ * Tests {@code @JsonbCreator} on a constructor when a constructor parameter name (via
+ * {@code @JsonbProperty}) conflicts with a public setter's property name.
+ *
+ * <p>The constructor parameter is named {@code "value"} via {@code @JsonbProperty}, which matches the
+ * bean property exposed by {@code setValue}/{@code getValue}. The constructor routes the JSON value to
+ * the separate field {@code creatorValue} (uppercased), so the setter must never be called for that key.
+ *
+ * <p>Expected outcomes after deserializing {@code {"value":"hello"}}:
+ * <ul>
+ * <li>{@code getValue()} – {@code null} (the creator claimed the name; the setter is never invoked)</li>
+ * <li>{@code creatorValue} – {@code "HELLO"} (assigned inside the constructor)</li>
+ * </ul>
+ */
+public class CreatorConstructorSetterConflicts {
+
+ private String value;
+ public String creatorValue;
+
+ @JsonbCreator
+ public CreatorConstructorSetterConflicts(@JsonbProperty("value") String value) {
+ this.creatorValue = value.toUpperCase(Locale.ROOT);
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ /** Setter whose bean-property name {@code "value"} conflicts with the constructor parameter. */
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/src/test/java/org/eclipse/yasson/customization/model/CreatorFactoryNameConflicts.java b/src/test/java/org/eclipse/yasson/customization/model/CreatorFactoryNameConflicts.java
new file mode 100644
index 0000000..f7dd651
--- /dev/null
+++ b/src/test/java/org/eclipse/yasson/customization/model/CreatorFactoryNameConflicts.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2026 Eclipse and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+package org.eclipse.yasson.customization.model;
+
+import java.util.Locale;
+
+import jakarta.json.bind.annotation.JsonbCreator;
+import jakarta.json.bind.annotation.JsonbProperty;
+
+/**
+ * This class is used to test the behavior of {@code @JsonbCreator} on a factory method when a factory
+ * method parameter name (via {@code @JsonbProperty}) conflicts with the name of a public field.
+ *
+ * <p>The factory method parameter is named {@code "value"} via {@code @JsonbProperty}, which matches
+ * the public field {@code value}. The factory method routes that JSON value to the field
+ * {@code creatorValue} (converted to uppercase), leaving the public field {@code value} null.
+ *
+ * <p>Expected outcomes after deserializing {@code {"value":"hello"}}:
+ * <ul>
+ * <li>{@code value} – {@code null} (the creator claimed the name; it is never set via field injection)</li>
+ * <li>{@code creatorValue} – {@code "HELLO"} (assigned inside the factory method)</li>
+ * </ul>
+ */
+public class CreatorFactoryNameConflicts {
+
+ /** Public field whose JSON name conflicts with the factory method parameter. */
+ public String value;
+
+ /** Receives the transformed value from the factory method. */
+ public String creatorValue;
+
+ private CreatorFactoryNameConflicts() {
+ }
+
+ @JsonbCreator
+ public static CreatorFactoryNameConflicts create(@JsonbProperty("value") String value) {
+ CreatorFactoryNameConflicts instance = new CreatorFactoryNameConflicts();
+ instance.creatorValue = value.toUpperCase(Locale.ROOT);
+ return instance;
+ }
+}
diff --git a/src/test/java/org/eclipse/yasson/customization/model/CreatorFactorySetterConflicts.java b/src/test/java/org/eclipse/yasson/customization/model/CreatorFactorySetterConflicts.java
new file mode 100644
index 0000000..f13e052
--- /dev/null
+++ b/src/test/java/org/eclipse/yasson/customization/model/CreatorFactorySetterConflicts.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2026 Eclipse and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+package org.eclipse.yasson.customization.model;
+
+import java.util.Locale;
+
+import jakarta.json.bind.annotation.JsonbCreator;
+import jakarta.json.bind.annotation.JsonbProperty;
+
+/**
+ * Tests {@code @JsonbCreator} on a factory method when a factory method parameter name (via
+ * {@code @JsonbProperty}) conflicts with a public setter's property name.
+ *
+ * <p>The factory method parameter is named {@code "value"} via {@code @JsonbProperty}, which matches
+ * the bean property exposed by {@code setValue}/{@code getValue}. The factory method routes the JSON
+ * value to the separate field {@code creatorValue} (uppercased), so the setter must never be called
+ * for that key.
+ *
+ * <p>Expected outcomes after deserializing {@code {"value":"hello"}}:
+ * <ul>
+ * <li>{@code getValue()} – {@code null} (the creator claimed the name; the setter is never invoked)</li>
+ * <li>{@code creatorValue} – {@code "HELLO"} (assigned inside the factory method)</li>
+ * </ul>
+ */
+public class CreatorFactorySetterConflicts {
+
+ private String value;
+ public String creatorValue;
+
+ private CreatorFactorySetterConflicts() {
+ }
+
+ @JsonbCreator
+ public static CreatorFactorySetterConflicts create(@JsonbProperty("value") String value) {
+ CreatorFactorySetterConflicts instance = new CreatorFactorySetterConflicts();
+ instance.creatorValue = value.toUpperCase(Locale.ROOT);
+ return instance;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ /** Setter whose bean-property name {@code "value"} conflicts with the factory method parameter. */
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/src/test/java/org/eclipse/yasson/customization/model/CreatorIncompleteParameters.java b/src/test/java/org/eclipse/yasson/customization/model/CreatorIncompleteParameters.java
new file mode 100644
index 0000000..440321d
--- /dev/null
+++ b/src/test/java/org/eclipse/yasson/customization/model/CreatorIncompleteParameters.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2026 Eclipse and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+package org.eclipse.yasson.customization.model;
+
+import java.util.Locale;
+
+import jakarta.json.bind.annotation.JsonbCreator;
+import jakarta.json.bind.annotation.JsonbProperty;
+
+/**
+ * This class is used to test the behavior of @JsonbCreator when there are incomplete set of parameters in the constructor.
+ * The constructor parameter "declaredField" is annotated with @JsonbProperty("declaredField"),
+ * which should map the JSON property "declaredField" to the constructor parameter,
+ * and then assign it to the field "declaredField".
+ *
+ * The field "declaredField" should be set to the value of "declaredField" from the JSON, converted to uppercase.
+ * The field "notDeclaredField" should be set via the normal deserialization pathway since it is not provided in the constructor.
+ * The field "notDeclaredSetter" should be set via the normal deserialization pathway since it is not provided in the constructor and has a setter method.
+ *
+ * CreatorIncompleteParameters
+ */
+public class CreatorIncompleteParameters {
+ public String declaredField;
+ public String notDeclaredField;
+ private String notDeclaredSetter;
+
+ @JsonbCreator
+ public CreatorIncompleteParameters(@JsonbProperty("declaredField") String declaredField) {
+ this.declaredField = declaredField.toUpperCase(Locale.ROOT);
+ }
+
+ public void setNotDeclaredSetter(String notDeclaredSetter) {
+ this.notDeclaredSetter = notDeclaredSetter;
+ }
+
+ public String getNotDeclaredSetter() {
+ return notDeclaredSetter;
+ }
+}
diff --git a/src/test/java/org/eclipse/yasson/customization/model/CreatorNameConflicts.java b/src/test/java/org/eclipse/yasson/customization/model/CreatorNameConflicts.java
new file mode 100644
index 0000000..1d333be
--- /dev/null
+++ b/src/test/java/org/eclipse/yasson/customization/model/CreatorNameConflicts.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2026 Eclipse and/or its affiliates. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0,
+ * or the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
+ */
+
+package org.eclipse.yasson.customization.model;
+
+import java.util.Locale;
+
+import jakarta.json.bind.annotation.JsonbCreator;
+import jakarta.json.bind.annotation.JsonbProperty;
+
+/**
+ * This class is used to test the behavior of @JsonbCreator when there are name conflicts between constructor parameters and class fields.
+ * The constructor parameter "fromJson" is annotated with @JsonbProperty("fromJson"),
+ * which should map the JSON property "fromJson" to the constructor parameter, and then assign it to the field "fromCreator".
+ *
+ * The field "fromJson" should remain null since it is not assigned in the constructor.
+ * The field "fromCreator" should be set to the value of "fromJson" from the JSON, converted to uppercase.
+ * The field "notProvided" should remain null since it is not provided in the JSON and has no default value.
+ * The field "notDeclared" is an int and should be set to its default value (0) since it is not provided in the JSON.
+ *
+ * CreatorNameConflicts
+ */
+public class CreatorNameConflicts {
+ public String fromJson;
+ public String fromCreator;
+ public String notProvided;
+ public int notDeclared;
+
+ @JsonbCreator
+ public CreatorNameConflicts(
+ @JsonbProperty("fromJson") String fromJson,
+ @JsonbProperty("notDeclared") int notDeclared) {
+ this.fromCreator = fromJson.toUpperCase(Locale.ROOT);
+ this.notDeclared = notDeclared;
+ }
+}