Support retrieving lower bound from TypeVariable in Collection attribute (#580) Support retrieving lower bound from TypeVariable in Collection attribute
diff --git a/src/main/java/org/eclipse/yasson/internal/ReflectionUtils.java b/src/main/java/org/eclipse/yasson/internal/ReflectionUtils.java index 7247839..a5eac94 100644 --- a/src/main/java/org/eclipse/yasson/internal/ReflectionUtils.java +++ b/src/main/java/org/eclipse/yasson/internal/ReflectionUtils.java
@@ -240,6 +240,14 @@ } resolvedArgs[i] = new VariableTypeInheritanceSearch() .searchParametrizedType(typeToSearch, (TypeVariable<?>) variableType); + + if (resolvedArgs[i] == null) { + Type[] bounds = ((TypeVariable<?>) variableType).getBounds(); + if (Objects.nonNull(bounds) && bounds.length > 0) { + resolvedArgs[i] = bounds[0]; + } + } + if (resolvedArgs[i] == null) { if (typeToSearch instanceof Class) { return Object.class;
diff --git a/src/test/java/org/eclipse/yasson/defaultmapping/generics/GenericsTest.java b/src/test/java/org/eclipse/yasson/defaultmapping/generics/GenericsTest.java index 3bc88a0..b193521 100644 --- a/src/test/java/org/eclipse/yasson/defaultmapping/generics/GenericsTest.java +++ b/src/test/java/org/eclipse/yasson/defaultmapping/generics/GenericsTest.java
@@ -29,6 +29,8 @@ import jakarta.json.bind.Jsonb; import jakarta.json.bind.JsonbBuilder; import jakarta.json.bind.JsonbConfig; +import java.lang.reflect.Field; +import java.util.Collection; import org.eclipse.yasson.TestTypeToken; import org.eclipse.yasson.adapters.model.GenericBox; import org.eclipse.yasson.defaultmapping.generics.model.AnotherGenericTestClass; @@ -54,6 +56,7 @@ import org.junit.jupiter.api.Test; import static org.eclipse.yasson.Jsonbs.defaultJsonb; +import org.eclipse.yasson.defaultmapping.generics.model.LowerBoundTypeVariableWithCollectionAttributeClass; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -446,6 +449,32 @@ assertEquals(concreteContainer, finalGenericWrapper); } + @Test + public void lowerBoundTypeVariableInCollectionAttribute() throws Exception { + + Shape shape = new Shape(); + shape.setArea(5D); + + AnotherGenericTestClass<Integer, Shape> anotherGenericTestClass = new AnotherGenericTestClass<>(); + anotherGenericTestClass.field1 = 6; + anotherGenericTestClass.field2 = shape; + + List<AnotherGenericTestClass<Integer, Shape>> asList = Arrays.asList(anotherGenericTestClass); + + Jsonb jsonb = JsonbBuilder.create(); + String toJson = jsonb.toJson(asList); + + Field field = LowerBoundTypeVariableWithCollectionAttributeClass.class.getDeclaredField("value"); + + Type genericType = field.getGenericType(); + + List<AnotherGenericTestClass<Integer, Shape>> fromJson = jsonb.fromJson(toJson, genericType); + + assertEquals(5, fromJson.get(0).field2.getArea()); + assertEquals(6, fromJson.get(0).field1); + + } + public interface FunctionalInterface<T> { T getValue(); }
diff --git a/src/test/java/org/eclipse/yasson/defaultmapping/generics/model/LowerBoundTypeVariableWithCollectionAttributeClass.java b/src/test/java/org/eclipse/yasson/defaultmapping/generics/model/LowerBoundTypeVariableWithCollectionAttributeClass.java new file mode 100644 index 0000000..3b7198a --- /dev/null +++ b/src/test/java/org/eclipse/yasson/defaultmapping/generics/model/LowerBoundTypeVariableWithCollectionAttributeClass.java
@@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, 2022 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 + * 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.defaultmapping.generics.model; + +import java.util.Collection; + +/** + * @author Alessandro Moscatelli + */ +public class LowerBoundTypeVariableWithCollectionAttributeClass<T extends Shape> { + + private Collection<AnotherGenericTestClass<Integer, T>> value; + + public Collection<AnotherGenericTestClass<Integer, T>> getValue() { + return value; + } + + public void setValue(Collection<AnotherGenericTestClass<Integer, T>> value) { + this.value = value; + } + +}