Enabled usage of supertype adapters and serializers declared explicitly to allow "Immutables" to be usable. Signed-off-by: Roman Grigoriadi <roman.grigoriadi@oracle.com>
diff --git a/src/main/java/org/eclipse/yasson/internal/AnnotationIntrospector.java b/src/main/java/org/eclipse/yasson/internal/AnnotationIntrospector.java index bc363b4..1b9a226 100644 --- a/src/main/java/org/eclipse/yasson/internal/AnnotationIntrospector.java +++ b/src/main/java/org/eclipse/yasson/internal/AnnotationIntrospector.java
@@ -226,7 +226,7 @@ final Class<? extends JsonbAdapter> adapterClass = adapterAnnotation.value(); final AdapterBinding adapterBinding = jsonbContext.getComponentMatcher().introspectAdapterBinding(adapterClass, null); - if (expectedClass.isPresent() && !(ReflectionUtils.getRawType(adapterBinding.getBindingType()).equals(expectedClass.get()))) { + if (expectedClass.isPresent() && !(ReflectionUtils.getRawType(adapterBinding.getBindingType()).isAssignableFrom(expectedClass.get()))) { throw new JsonbException(Messages.getMessage(MessageKeys.ADAPTER_INCOMPATIBLE, adapterBinding.getBindingType(), expectedClass.get())); } return adapterBinding;
diff --git a/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java b/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java index 9b07327..1a25469 100644 --- a/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java +++ b/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
@@ -197,16 +197,18 @@ if (componentBindingType.equals(runtimeType)) { return true; } + + if (componentBindingType instanceof Class && runtimeType instanceof Class) { + return ((Class<?>) componentBindingType).isAssignableFrom((Class) runtimeType); + } + //don't try to runtime generic scan if not needed if (!jsonbContext.genericComponentsPresent()) { return false; } - if (componentBindingType instanceof Class && runtimeType instanceof Class) { - //for polymorphic adapters - return ((Class<?>) componentBindingType).isAssignableFrom((Class) runtimeType); - } + return runtimeType instanceof ParameterizedType && componentBindingType instanceof ParameterizedType && - ReflectionUtils.getRawType(runtimeType) == ReflectionUtils.getRawType(componentBindingType) && + ReflectionUtils.getRawType(componentBindingType).isAssignableFrom(ReflectionUtils.getRawType(runtimeType)) && matchTypeArguments((ParameterizedType) runtimeType, (ParameterizedType) componentBindingType); }
diff --git a/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java b/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java index f8ab20a..c2fc5ad 100644 --- a/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java +++ b/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java
@@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2018 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. @@ -15,7 +15,17 @@ import org.eclipse.yasson.TestTypeToken; -import org.eclipse.yasson.adapters.model.*; +import org.eclipse.yasson.adapters.model.AdaptedPojo; +import org.eclipse.yasson.adapters.model.Author; +import org.eclipse.yasson.adapters.model.Box; +import org.eclipse.yasson.adapters.model.BoxToCrateCompatibleGenericsAdapter; +import org.eclipse.yasson.adapters.model.BoxToCratePropagatedIntegerStringAdapter; +import org.eclipse.yasson.adapters.model.Crate; +import org.eclipse.yasson.adapters.model.GenericBox; +import org.eclipse.yasson.adapters.model.IntegerListToStringAdapter; +import org.eclipse.yasson.adapters.model.JsonObjectPojo; +import org.eclipse.yasson.adapters.model.SupertypeAdapterPojo; +import org.eclipse.yasson.adapters.model.UUIDContainer; import org.junit.Assert; import org.junit.Test; @@ -24,7 +34,12 @@ import javax.json.bind.JsonbConfig; import javax.json.bind.adapter.JsonbAdapter; import java.math.BigDecimal; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; import static org.junit.Assert.assertEquals; @@ -435,4 +450,16 @@ Assert.assertEquals(uuid, uuidContainer.getUuidClsBased()); Assert.assertEquals(uuid, uuidContainer.getUuidIfcBased()); } + + @Test + public void testSupertypeAdapter() { + jsonb = JsonbBuilder.create(); + SupertypeAdapterPojo pojo = new SupertypeAdapterPojo(); + pojo.setNumberInteger(10); + pojo.setSerializableInteger(11); + Assert.assertEquals("{\"numberInteger\":\"11\",\"serializableInteger\":12}", jsonb.toJson(pojo)); + pojo = jsonb.fromJson("{\"numberInteger\":\"11\",\"serializableInteger\":12}", SupertypeAdapterPojo.class); + Assert.assertEquals(Integer.valueOf(10), pojo.getNumberInteger()); + Assert.assertEquals(Integer.valueOf(11), pojo.getSerializableInteger()); + } }
diff --git a/src/test/java/org/eclipse/yasson/adapters/model/NumberAdapter.java b/src/test/java/org/eclipse/yasson/adapters/model/NumberAdapter.java new file mode 100644 index 0000000..205ef59 --- /dev/null +++ b/src/test/java/org/eclipse/yasson/adapters/model/NumberAdapter.java
@@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2018 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 v1.0 and Eclipse Distribution License v. 1.0 + * which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + ******************************************************************************/ +package org.eclipse.yasson.adapters.model; + +import javax.json.bind.adapter.JsonbAdapter; + +public class NumberAdapter implements JsonbAdapter<Number, String> { + @Override + public String adaptToJson(Number obj) throws Exception { + return Integer.valueOf(((Integer)obj) + 1).toString(); + } + + @Override + public Number adaptFromJson(String obj) throws Exception { + return Integer.parseInt(obj) - 1; + } +}
diff --git a/src/test/java/org/eclipse/yasson/adapters/model/SerializableAdapter.java b/src/test/java/org/eclipse/yasson/adapters/model/SerializableAdapter.java new file mode 100644 index 0000000..59bdfac --- /dev/null +++ b/src/test/java/org/eclipse/yasson/adapters/model/SerializableAdapter.java
@@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2018 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 v1.0 and Eclipse Distribution License v. 1.0 + * which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + ******************************************************************************/ +package org.eclipse.yasson.adapters.model; + +import javax.json.bind.adapter.JsonbAdapter; +import java.io.Serializable; + +public class SerializableAdapter implements JsonbAdapter<Serializable, Integer> { + @Override + public Integer adaptToJson(Serializable obj) throws Exception { + return Integer.valueOf(obj.toString()) + 1; + } + + @Override + public Serializable adaptFromJson(Integer obj) throws Exception { + return obj - 1; + } +}
diff --git a/src/test/java/org/eclipse/yasson/adapters/model/SupertypeAdapterPojo.java b/src/test/java/org/eclipse/yasson/adapters/model/SupertypeAdapterPojo.java new file mode 100644 index 0000000..c7ef3f8 --- /dev/null +++ b/src/test/java/org/eclipse/yasson/adapters/model/SupertypeAdapterPojo.java
@@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2018 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 v1.0 and Eclipse Distribution License v. 1.0 + * which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + ******************************************************************************/ +package org.eclipse.yasson.adapters.model; + +import javax.json.bind.annotation.JsonbTypeAdapter; + +public class SupertypeAdapterPojo { + + @JsonbTypeAdapter(NumberAdapter.class) + private Integer numberInteger; + + @JsonbTypeAdapter(SerializableAdapter.class) + private Integer serializableInteger; + + public Integer getNumberInteger() { + return numberInteger; + } + + public void setNumberInteger(Integer numberInteger) { + this.numberInteger = numberInteger; + } + + public Integer getSerializableInteger() { + return serializableInteger; + } + + public void setSerializableInteger(Integer serializableInteger) { + this.serializableInteger = serializableInteger; + } +}
diff --git a/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java b/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java index f470943..41823c9 100644 --- a/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java +++ b/src/test/java/org/eclipse/yasson/serializers/SerializersTest.java
@@ -13,7 +13,25 @@ package org.eclipse.yasson.serializers; -import org.eclipse.yasson.serializers.model.*; +import org.eclipse.yasson.serializers.model.AnnotatedWithSerializerType; +import org.eclipse.yasson.serializers.model.Author; +import org.eclipse.yasson.serializers.model.Box; +import org.eclipse.yasson.serializers.model.BoxWithAnnotations; +import org.eclipse.yasson.serializers.model.Crate; +import org.eclipse.yasson.serializers.model.CrateDeserializer; +import org.eclipse.yasson.serializers.model.CrateDeserializerWithConversion; +import org.eclipse.yasson.serializers.model.CrateInner; +import org.eclipse.yasson.serializers.model.CrateJsonObjectDeserializer; +import org.eclipse.yasson.serializers.model.CrateSerializer; +import org.eclipse.yasson.serializers.model.CrateSerializerWithConversion; +import org.eclipse.yasson.serializers.model.NumberDeserializer; +import org.eclipse.yasson.serializers.model.NumberSerializer; +import org.eclipse.yasson.serializers.model.RecursiveDeserializer; +import org.eclipse.yasson.serializers.model.RecursiveSerializer; +import org.eclipse.yasson.serializers.model.SimpleAnnotatedSerializedArrayContainer; +import org.eclipse.yasson.serializers.model.SimpleContainer; +import org.eclipse.yasson.serializers.model.StringWrapper; +import org.eclipse.yasson.serializers.model.SupertypeSerializerPojo; import org.junit.Assert; import org.junit.Test; @@ -282,6 +300,21 @@ Assert.assertEquals("Connor", result.getLastName()); } + @Test + public void testSupertypeSerializer() { + Jsonb jsonb = JsonbBuilder.create( + new JsonbConfig().withSerializers(new NumberSerializer()) + .withDeserializers(new NumberDeserializer())); + SupertypeSerializerPojo pojo = new SupertypeSerializerPojo(); + pojo.setNumberInteger(10); + pojo.setAnotherNumberInteger(11); + Assert.assertEquals("{\"anotherNumberInteger\":\"12\",\"numberInteger\":\"11\"}", jsonb.toJson(pojo)); + + pojo = jsonb.fromJson("{\"anotherNumberInteger\":\"12\",\"numberInteger\":\"11\"}", SupertypeSerializerPojo.class); + Assert.assertEquals(Integer.valueOf(10), pojo.getNumberInteger()); + Assert.assertEquals(Integer.valueOf(11), pojo.getAnotherNumberInteger()); + } + private Box createPojoWithDates() { Date date = getExpectedDate(); Box box = createPojo();
diff --git a/src/test/java/org/eclipse/yasson/serializers/model/NumberDeserializer.java b/src/test/java/org/eclipse/yasson/serializers/model/NumberDeserializer.java new file mode 100644 index 0000000..0db5d9d --- /dev/null +++ b/src/test/java/org/eclipse/yasson/serializers/model/NumberDeserializer.java
@@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2018 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 v1.0 and Eclipse Distribution License v. 1.0 + * which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + ******************************************************************************/ +package org.eclipse.yasson.serializers.model; + +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.stream.JsonParser; +import java.lang.reflect.Type; + +public class NumberDeserializer implements JsonbDeserializer<Number> { + @Override + public Number deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) { + return Integer.valueOf(parser.getString()) - 1; + } +}
diff --git a/src/test/java/org/eclipse/yasson/serializers/model/NumberSerializer.java b/src/test/java/org/eclipse/yasson/serializers/model/NumberSerializer.java new file mode 100644 index 0000000..3e49bda --- /dev/null +++ b/src/test/java/org/eclipse/yasson/serializers/model/NumberSerializer.java
@@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2018 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 v1.0 and Eclipse Distribution License v. 1.0 + * which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + ******************************************************************************/ +package org.eclipse.yasson.serializers.model; + +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; + +public class NumberSerializer implements JsonbSerializer<Number> { + @Override + public void serialize(Number obj, JsonGenerator generator, SerializationContext ctx) { + generator.write(Integer.valueOf(obj.intValue() + 1).toString()); + } +}
diff --git a/src/test/java/org/eclipse/yasson/serializers/model/SupertypeSerializerPojo.java b/src/test/java/org/eclipse/yasson/serializers/model/SupertypeSerializerPojo.java new file mode 100644 index 0000000..ad8b943 --- /dev/null +++ b/src/test/java/org/eclipse/yasson/serializers/model/SupertypeSerializerPojo.java
@@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2018 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 v1.0 and Eclipse Distribution License v. 1.0 + * which accompanies this distribution. + * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + ******************************************************************************/ +package org.eclipse.yasson.serializers.model; + +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; + +public class SupertypeSerializerPojo { + + + @JsonbTypeSerializer(NumberSerializer.class) + @JsonbTypeDeserializer(NumberDeserializer.class) + private Integer numberInteger; + + //Serializers bound with JsonbConfig for this one. + private Integer anotherNumberInteger; + + public Integer getNumberInteger() { + return numberInteger; + } + + public void setNumberInteger(Integer numberInteger) { + this.numberInteger = numberInteger; + } + + public Integer getAnotherNumberInteger() { + return anotherNumberInteger; + } + + public void setAnotherNumberInteger(Integer anotherNumberInteger) { + this.anotherNumberInteger = anotherNumberInteger; + } +}