test: https://github.com/eclipse-ee4j/yasson/issues/762 Co-authored-by-AI: IBM Bob (1.126.0+bob2.1.0)
diff --git a/src/test/java/org/eclipse/yasson/customization/transients/JsonbTransientTest.java b/src/test/java/org/eclipse/yasson/customization/transients/JsonbTransientTest.java index c1d36a0..bf633cd 100644 --- a/src/test/java/org/eclipse/yasson/customization/transients/JsonbTransientTest.java +++ b/src/test/java/org/eclipse/yasson/customization/transients/JsonbTransientTest.java
@@ -215,6 +215,78 @@ assertNull(result.componentAndAccessorTransient()); } + /** + * Verifies that all meaningful combinations of {@link JsonbTransient} placement on fields, + * getters, and setters are correctly honoured when deserialization goes through an explicit + * {@link jakarta.json.bind.annotation.JsonbCreator} constructor. + * + * <p>Combinations verified: + * <ul> + * <li>field only → write-transient: JSON value ignored, constructor gets {@code null}</li> + * <li>getter only → read-transient only: JSON value still bound (write allowed)</li> + * <li>setter only → write-transient: JSON value ignored, constructor gets {@code null}</li> + * <li>field + getter → write-transient: JSON value ignored</li> + * <li>field + setter → write-transient: JSON value ignored</li> + * <li>getter + setter → write-transient: JSON value ignored</li> + * <li>field + getter + setter → write-transient: JSON value ignored</li> + * </ul> + */ + @Test + public void testJsonbTransientWithCreatorDeserialize() { + JsonbTransientWithCreator result = defaultJsonb.fromJson( + "{" + + "\"plainProperty\":\"plain value\"," + + "\"fieldTransient\":\"field transient value\"," + + "\"getterTransient\":\"getter transient value\"," + + "\"setterTransient\":\"setter transient value\"," + + "\"fieldAndGetterTransient\":\"field+getter transient value\"," + + "\"fieldAndSetterTransient\":\"field+setter transient value\"," + + "\"getterAndSetterTransient\":\"getter+setter transient value\"," + + "\"allTransient\":\"all transient value\"" + + "}", + JsonbTransientWithCreator.class); + + // Not transient — always populated + assertEquals("plain value", result.plainProperty); + + // Write-transient cases: JSON value must be discarded; constructor slot receives null + assertNull(result.fieldTransient, "@JsonbTransient on field: should suppress deserialization via @JsonbCreator"); + assertNull(result.setterTransient, "@JsonbTransient on setter: should suppress deserialization via @JsonbCreator"); + assertNull(result.fieldAndGetterTransient, "@JsonbTransient on field+getter: should suppress deserialization via @JsonbCreator"); + assertNull(result.fieldAndSetterTransient, "@JsonbTransient on field+setter: should suppress deserialization via @JsonbCreator"); + assertNull(result.getterAndSetterTransient,"@JsonbTransient on getter+setter: should suppress deserialization via @JsonbCreator"); + assertNull(result.allTransient, "@JsonbTransient on field+getter+setter: should suppress deserialization via @JsonbCreator"); + + // Getter-only transient: read-transient only, write is still allowed + assertEquals("getter transient value", result.getterTransient, + "@JsonbTransient on getter only: deserialization should still be allowed via @JsonbCreator"); + } + + /** + * Verifies that the serialization side of {@link JsonbTransient} on a class with a + * {@link jakarta.json.bind.annotation.JsonbCreator} constructor is also respected. + */ + @Test + public void testJsonbTransientWithCreatorSerialize() { + JsonbTransientWithCreator instance = new JsonbTransientWithCreator( + "plain value", + "field transient value", + "getter transient value", + "setter transient value", + "field+getter transient value", + "field+setter transient value", + "getter+setter transient value", + "all transient value" + ); + + // Only plainProperty and setterTransient should appear: + // - setterTransient has @JsonbTransient only on setter → read-transient=false → serialized + // - getterTransient has @JsonbTransient on getter → read-transient=true → suppressed + // - everything else is fully transient + assertEquals("{\"plainProperty\":\"plain value\",\"setterTransient\":\"setter transient value\"}", + defaultJsonb.toJson(instance)); + } + @Test public void testTransientGetterNoField() { TransientGetterNoField pojo = new TransientGetterNoField();
diff --git a/src/test/java/org/eclipse/yasson/customization/transients/models/JsonbTransientWithCreator.java b/src/test/java/org/eclipse/yasson/customization/transients/models/JsonbTransientWithCreator.java new file mode 100644 index 0000000..bcced3a --- /dev/null +++ b/src/test/java/org/eclipse/yasson/customization/transients/models/JsonbTransientWithCreator.java
@@ -0,0 +1,110 @@ +/* + * Copyright (c) 2026 Contributors to the Eclipse Foundation + * + * 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.transients.models; + +import jakarta.json.bind.annotation.JsonbCreator; +import jakarta.json.bind.annotation.JsonbProperty; +import jakarta.json.bind.annotation.JsonbTransient; + +/** + * Regular class with an explicit {@link JsonbCreator} constructor that exercises every + * meaningful combination of {@link JsonbTransient} placement (field, getter, setter). + * + * <p>Expected deserialization semantics: + * <ul> + * <li>{@code plainProperty} – not transient; always populated.</li> + * <li>{@code fieldTransient} – {@code @JsonbTransient} on field → both directions + * suppressed; constructor receives {@code null}.</li> + * <li>{@code getterTransient} – {@code @JsonbTransient} on getter only → serialization + * suppressed, deserialization still populates the field.</li> + * <li>{@code setterTransient} – {@code @JsonbTransient} on setter only → deserialization + * suppressed; constructor receives {@code null}.</li> + * <li>{@code fieldAndGetterTransient} – field + getter → both directions suppressed.</li> + * <li>{@code fieldAndSetterTransient} – field + setter → both directions suppressed.</li> + * <li>{@code getterAndSetterTransient} – getter + setter → both directions suppressed.</li> + * <li>{@code allTransient} – field + getter + setter → both directions suppressed.</li> + * </ul> + */ +public class JsonbTransientWithCreator { + + /** No annotation — always visible in both directions. */ + public String plainProperty; + + /** {@code @JsonbTransient} on the backing field. */ + @JsonbTransient + public String fieldTransient; + + /** {@code @JsonbTransient} on the getter only. */ + public String getterTransient; + + /** {@code @JsonbTransient} on the setter only. */ + public String setterTransient; + + /** {@code @JsonbTransient} on both field and getter. */ + @JsonbTransient + public String fieldAndGetterTransient; + + /** {@code @JsonbTransient} on both field and setter. */ + @JsonbTransient + public String fieldAndSetterTransient; + + /** {@code @JsonbTransient} on both getter and setter. */ + public String getterAndSetterTransient; + + /** {@code @JsonbTransient} on all three: field, getter, and setter. */ + @JsonbTransient + public String allTransient; + + @JsonbCreator + public JsonbTransientWithCreator(@JsonbProperty("plainProperty") String plainProperty, + @JsonbProperty("fieldTransient") String fieldTransient, + @JsonbProperty("getterTransient") String getterTransient, + @JsonbProperty("setterTransient") String setterTransient, + @JsonbProperty("fieldAndGetterTransient") String fieldAndGetterTransient, + @JsonbProperty("fieldAndSetterTransient") String fieldAndSetterTransient, + @JsonbProperty("getterAndSetterTransient") String getterAndSetterTransient, + @JsonbProperty("allTransient") String allTransient) { + this.plainProperty = plainProperty; + this.fieldTransient = fieldTransient; + this.getterTransient = getterTransient; + this.setterTransient = setterTransient; + this.fieldAndGetterTransient = fieldAndGetterTransient; + this.fieldAndSetterTransient = fieldAndSetterTransient; + this.getterAndSetterTransient = getterAndSetterTransient; + this.allTransient = allTransient; + } + + @JsonbTransient + public String getGetterTransient() { return getterTransient; } + + @JsonbTransient + public void setSetterTransient(String setterTransient) { this.setterTransient = setterTransient; } + + @JsonbTransient + public String getFieldAndGetterTransient() { return fieldAndGetterTransient; } + + @JsonbTransient + public void setFieldAndSetterTransient(String fieldAndSetterTransient) { this.fieldAndSetterTransient = fieldAndSetterTransient; } + + @JsonbTransient + public String getGetterAndSetterTransient() { return getterAndSetterTransient; } + + @JsonbTransient + public void setGetterAndSetterTransient(String getterAndSetterTransient) { this.getterAndSetterTransient = getterAndSetterTransient; } + + @JsonbTransient + public String getAllTransient() { return allTransient; } + + @JsonbTransient + public void setAllTransient(String allTransient) { this.allTransient = allTransient; } +}