Merge pull request #312 from aguibert/property-type-mismatch
Apply adapters based on property read/write type
diff --git a/pom.xml b/pom.xml
index f0b2731..fbc29be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -351,6 +351,7 @@
<goal>test</goal>
</goals>
<configuration>
+ <trimStackTrace>false</trimStackTrace>
<excludes>
<exclude>**/JavaxNamingExcludedTest.class</exclude>
<exclude>**/AnnotationIntrospectorWithoutOptionalModulesTest.class</exclude>
diff --git a/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java b/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
index 8041412..c22674e 100644
--- a/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
+++ b/src/main/java/org/eclipse/yasson/internal/ComponentMatcher.java
@@ -172,20 +172,18 @@
* @param customization customization with component info
* @return components info if present
*/
- public Optional<AdapterBinding> getAdapterBinding(Type propertyRuntimeType, ComponentBoundCustomization customization) {
- if (customization == null || customization.getAdapterBinding() == null) {
+ public Optional<AdapterBinding> getSerializeAdapterBinding(Type propertyRuntimeType, ComponentBoundCustomization customization) {
+ if (customization == null || customization.getSerializeAdapterBinding() == null) {
return searchComponentBinding(propertyRuntimeType, ComponentBindings::getAdapterInfo);
}
- return Optional.of(customization.getAdapterBinding());
+ return Optional.of(customization.getSerializeAdapterBinding());
}
-
- private <T extends AbstractComponentBinding> Optional<T> getComponentBinding(Type propertyRuntimeType, T componentBinding) {
- //need runtime check, ParameterizedType property may have generic components assigned which is not compatible
- //for given runtime type
- if (matches(propertyRuntimeType, componentBinding.getBindingType())) {
- return Optional.of(componentBinding);
+
+ public Optional<AdapterBinding> getDeserializeAdapterBinding(Type propertyRuntimeType, ComponentBoundCustomization customization) {
+ if (customization == null || customization.getDeserializeAdapterBinding() == null) {
+ return searchComponentBinding(propertyRuntimeType, ComponentBindings::getAdapterInfo);
}
- return Optional.empty();
+ return Optional.of(customization.getDeserializeAdapterBinding());
}
private <T extends AbstractComponentBinding> Optional<T> searchComponentBinding(Type runtimeType, ComponentSupplier<T> supplier) {
diff --git a/src/main/java/org/eclipse/yasson/internal/Unmarshaller.java b/src/main/java/org/eclipse/yasson/internal/Unmarshaller.java
index b0c63ff..9d9f743 100644
--- a/src/main/java/org/eclipse/yasson/internal/Unmarshaller.java
+++ b/src/main/java/org/eclipse/yasson/internal/Unmarshaller.java
@@ -16,13 +16,11 @@
import org.eclipse.yasson.internal.model.ClassModel;
import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;
-import org.eclipse.yasson.internal.serializer.CurrentItem;
import org.eclipse.yasson.internal.serializer.DefaultSerializers;
import org.eclipse.yasson.internal.serializer.DeserializerBuilder;
import javax.json.bind.JsonbException;
import javax.json.bind.serializer.DeserializationContext;
-import javax.json.bind.serializer.JsonbDeserializer;
import javax.json.stream.JsonParser;
import java.lang.reflect.Type;
import java.util.logging.Logger;
diff --git a/src/main/java/org/eclipse/yasson/internal/model/CreatorModel.java b/src/main/java/org/eclipse/yasson/internal/model/CreatorModel.java
index 11bf0df..26e2834 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/CreatorModel.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/CreatorModel.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 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.
@@ -51,7 +51,7 @@
JsonbNumberFormatter constructorNumberFormatter = context.getAnnotationIntrospector().getConstructorNumberFormatter(annotated);
JsonbDateFormatter constructorDateFormatter = context.getAnnotationIntrospector().getConstructorDateFormatter(annotated);
final JsonbAnnotatedElement<Class<?>> clsElement = annotationIntrospector.collectAnnotations(parameter.getType());
- final CustomizationBuilder builder = new ClassCustomizationBuilder();
+ final ClassCustomizationBuilder builder = new ClassCustomizationBuilder();
builder.setAdapterInfo(annotationIntrospector.getAdapterBinding(clsElement));
builder.setDeserializerBinding(annotationIntrospector.getDeserializerBinding(clsElement));
builder.setSerializerBinding(annotationIntrospector.getSerializerBinding(clsElement));
diff --git a/src/main/java/org/eclipse/yasson/internal/model/PropertyModel.java b/src/main/java/org/eclipse/yasson/internal/model/PropertyModel.java
index e00866c..9943e8e 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/PropertyModel.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/PropertyModel.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 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.
@@ -113,8 +113,8 @@
if (!ReflectionUtils.isResolvedType(serializationType)) {
return null;
}
- if (customization.getAdapterBinding() != null) {
- return new AdaptedObjectSerializer<>(classModel, customization.getAdapterBinding());
+ if (customization.getSerializeAdapterBinding() != null) {
+ return new AdaptedObjectSerializer<>(classModel, customization.getSerializeAdapterBinding());
}
if (customization.getSerializerBinding() != null) {
return new UserSerializerSerializer<>(classModel, customization.getSerializerBinding().getJsonbSerializer());
@@ -147,14 +147,6 @@
return getterMethodType == null ? propertyType : getterMethodType.getMethodType();
}
- private AdapterBinding getUserAdapterBinding(Property property, JsonbContext jsonbContext) {
- final AdapterBinding adapterBinding = jsonbContext.getAnnotationIntrospector().getAdapterBinding(property);
- if (adapterBinding != null) {
- return adapterBinding;
- }
- return jsonbContext.getComponentMatcher().getAdapterBinding(propertyType, null).orElse(null);
- }
-
private SerializerBinding<?> getUserSerializerBinding(Property property, JsonbContext jsonbContext) {
final SerializerBinding serializerBinding = jsonbContext.getAnnotationIntrospector().getSerializerBinding(property);
if (serializerBinding != null) {
@@ -202,7 +194,14 @@
builder.setDeserializerBinding(introspector.getDeserializerBinding(property));
}
- builder.setAdapterInfo(getUserAdapterBinding(property, jsonbContext));
+ final AdapterBinding adapterBinding = jsonbContext.getAnnotationIntrospector().getAdapterBinding(property);
+ if (adapterBinding != null) {
+ builder.setSerializeAdapter(adapterBinding);
+ builder.setDeserializeAdapter(adapterBinding);
+ } else {
+ builder.setSerializeAdapter(jsonbContext.getComponentMatcher().getSerializeAdapterBinding(getPropertySerializationType(), null).orElse(null));
+ builder.setDeserializeAdapter(jsonbContext.getComponentMatcher().getDeserializeAdapterBinding(getPropertyDeserializationType(), null).orElse(null));
+ }
introspectDateFormatter(property, introspector, builder, jsonbContext);
introspectNumberFormatter(property, introspector, builder);
@@ -327,15 +326,6 @@
}
/**
- * Runtime type of a property. May be a TypeVariable or WildcardType.
- *
- * @return type of a property
- */
- public Type getPropertyType() {
- return propertyType;
- }
-
- /**
* Model of declaring class of this property.
* @return class model
*/
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/ComponentBoundCustomization.java b/src/main/java/org/eclipse/yasson/internal/model/customization/ComponentBoundCustomization.java
index 47a7e9d..3b107e8 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/ComponentBoundCustomization.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/ComponentBoundCustomization.java
@@ -1,3 +1,12 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 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.internal.model.customization;
import org.eclipse.yasson.internal.components.AdapterBinding;
@@ -10,11 +19,14 @@
public interface ComponentBoundCustomization {
/**
- * Adapter wrapper class with resolved generic information.
- *
- * @return components wrapper
+ * @return Adapter wrapper class with resolved generic information.
*/
- AdapterBinding getAdapterBinding();
+ AdapterBinding getSerializeAdapterBinding();
+
+ /**
+ * @return Adapter wrapper class with resolved generic information.
+ */
+ AdapterBinding getDeserializeAdapterBinding();
/**
* Serializer wrapper with resolved generic info.
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/CustomizationBase.java b/src/main/java/org/eclipse/yasson/internal/model/customization/CustomizationBase.java
index cad97b0..587e852 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/CustomizationBase.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/CustomizationBase.java
@@ -1,3 +1,12 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 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.internal.model.customization;
import org.eclipse.yasson.internal.components.AdapterBinding;
@@ -36,7 +45,7 @@
*/
public CustomizationBase(CustomizationBase other) {
this.nillable = other.isNillable();
- this.adapterBinding = other.getAdapterBinding();
+ this.adapterBinding = other.getSerializeAdapterBinding();
this.serializerBinding = other.getSerializerBinding();
this.deserializerBinding = other.getDeserializerBinding();
}
@@ -50,12 +59,12 @@
return nillable;
}
- /**
- * Adapter wrapper class with resolved generic information.
- *
- * @return components wrapper
- */
- public AdapterBinding getAdapterBinding() {
+ public AdapterBinding getSerializeAdapterBinding() {
+ return adapterBinding;
+ }
+
+ @Override
+ public AdapterBinding getDeserializeAdapterBinding() {
return adapterBinding;
}
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomization.java b/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomization.java
index ce30100..8c05266 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomization.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomization.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 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.
@@ -10,9 +10,9 @@
* Contributors:
* Roman Grigoriadi
******************************************************************************/
-
package org.eclipse.yasson.internal.model.customization;
+import org.eclipse.yasson.internal.components.AdapterBinding;
import org.eclipse.yasson.internal.serializer.JsonbDateFormatter;
import org.eclipse.yasson.internal.serializer.JsonbNumberFormatter;
@@ -24,22 +24,21 @@
public class PropertyCustomization extends CustomizationBase {
private final String jsonReadName;
-
private final String jsonWriteName;
private final JsonbNumberFormatter serializeNumberFormatter;
-
private final JsonbNumberFormatter deserializeNumberFormatter;
private final JsonbDateFormatter serializeDateFormatter;
-
private final JsonbDateFormatter deserializeDateFormatter;
+
+ private final AdapterBinding serializeAdapter;
+ private final AdapterBinding deserializeAdapter;
private boolean readTransient;
-
private boolean writeTransient;
- private final Class implementationClass;
+ private final Class<?> implementationClass;
/**
* Copies properties from builder an creates immutable instance.
@@ -48,6 +47,8 @@
*/
public PropertyCustomization(PropertyCustomizationBuilder builder) {
super(builder);
+ this.serializeAdapter = builder.getSerializeAdapter();
+ this.deserializeAdapter = builder.getDeserializeAdapter();
this.jsonReadName = builder.getJsonReadName();
this.jsonWriteName = builder.getJsonWriteName();
this.serializeNumberFormatter = builder.getSerializeNumberFormatter();
@@ -121,8 +122,18 @@
*
* @return class implementing property interface
*/
- public Class getImplementationClass() {
+ public Class<?> getImplementationClass() {
return implementationClass;
}
+
+ @Override
+ public AdapterBinding getDeserializeAdapterBinding() {
+ return deserializeAdapter;
+ }
+
+ @Override
+ public AdapterBinding getSerializeAdapterBinding() {
+ return serializeAdapter;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomizationBuilder.java b/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomizationBuilder.java
index 98160f4..e36b294 100644
--- a/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomizationBuilder.java
+++ b/src/main/java/org/eclipse/yasson/internal/model/customization/PropertyCustomizationBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 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.
@@ -10,9 +10,9 @@
* Contributors:
* Ehsan Zaery Moghaddam (zaerymoghaddam@gmail.com)
******************************************************************************/
-
package org.eclipse.yasson.internal.model.customization;
+import org.eclipse.yasson.internal.components.AdapterBinding;
import org.eclipse.yasson.internal.serializer.JsonbDateFormatter;
import org.eclipse.yasson.internal.serializer.JsonbNumberFormatter;
@@ -24,20 +24,19 @@
public class PropertyCustomizationBuilder extends CustomizationBuilder {
private String jsonReadName;
-
private String jsonWriteName;
private JsonbNumberFormatter serializeNumberFormatter;
-
private JsonbNumberFormatter deserializeNumberFormatter;
private JsonbDateFormatter serializeDateFormatter;
-
private JsonbDateFormatter deserializeDateFormatter;
private boolean readTransient;
-
private boolean writeTransient;
+
+ private AdapterBinding serializeAdapter;
+ private AdapterBinding deserializeAdapter;
private Class implementationClass;
@@ -212,4 +211,30 @@
public void setImplementationClass(Class implementationClass) {
this.implementationClass = implementationClass;
}
+
+ @Override
+ public void setAdapterInfo(AdapterBinding adapterInfo) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AdapterBinding getAdapterInfo() {
+ return null;
+ }
+
+ public AdapterBinding getSerializeAdapter() {
+ return serializeAdapter;
+ }
+
+ public void setSerializeAdapter(AdapterBinding adapter) {
+ this.serializeAdapter = adapter;
+ }
+
+ public AdapterBinding getDeserializeAdapter() {
+ return deserializeAdapter;
+ }
+
+ public void setDeserializeAdapter(AdapterBinding adapter) {
+ this.deserializeAdapter = adapter;
+ }
}
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java b/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java
index 6e939ce..29607d4 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/DeserializerBuilder.java
@@ -76,7 +76,6 @@
*
* @return built item
*/
- @SuppressWarnings("unchecked")
public JsonbDeserializer<?> build() {
runtimeType = resolveRuntimeType();
Class<?> rawType = ReflectionUtils.getRawType(getRuntimeType());
@@ -95,7 +94,7 @@
}
//Second user components is registered.
- Optional<AdapterBinding> adapterBinding = componentMatcher.getAdapterBinding(getRuntimeType(), componentBoundCustomization);
+ Optional<AdapterBinding> adapterBinding = componentMatcher.getDeserializeAdapterBinding(getRuntimeType(), componentBoundCustomization);
if (adapterBinding.isPresent()) {
adapterInfoOptional = adapterBinding;
runtimeType = adapterInfoOptional.get().getToType();
@@ -247,7 +246,7 @@
private Class<?> getInterfaceMappedType(Class<?> interfaceType) {
if (interfaceType.isInterface()) {
- Class implementationClass = null;
+ Class<?> implementationClass = null;
//annotation
if (customization instanceof PropertyCustomization) {
implementationClass = ((PropertyCustomization) customization).getImplementationClass();
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java
index f1a603e..9ced476 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectDeserializer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2015, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019 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.
@@ -28,7 +28,6 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.logging.Logger;
/**
* Item for handling all types of unknown objects by reflection, parsing their fields, according to json key name.
@@ -59,8 +58,6 @@
}
}
- private static final Logger log = Logger.getLogger(ObjectDeserializer.class.getName());
-
private Map<String, ValueWrapper> values = new LinkedHashMap<>();
private T instance;
@@ -137,7 +134,7 @@
if (model == null) {
return;
}
- values.put(model.getReadName(), new ValueWrapper(model, convertNullToOptionalEmpty(model.getPropertyType(), result)));
+ values.put(model.getReadName(), new ValueWrapper(model, convertNullToOptionalEmpty(model.getPropertyDeserializationType(), result)));
}
@Override
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
index 7ab0f6a..c8350aa 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/ObjectSerializer.java
@@ -10,7 +10,6 @@
* Contributors:
* Roman Grigoriadi
******************************************************************************/
-
package org.eclipse.yasson.internal.serializer;
import org.eclipse.yasson.internal.Marshaller;
@@ -101,7 +100,7 @@
return;
}
- Optional<Type> runtimeTypeOptional = ReflectionUtils.resolveOptionalType(this, propertyModel.getPropertyType());
+ Optional<Type> runtimeTypeOptional = ReflectionUtils.resolveOptionalType(this, propertyModel.getPropertySerializationType());
Type genericType = runtimeTypeOptional.orElse(null);
final JsonbSerializer<?> serializer = new SerializerBuilder(marshaller.getJsonbContext())
.withWrapper(this)
diff --git a/src/main/java/org/eclipse/yasson/internal/serializer/SerializerBuilder.java b/src/main/java/org/eclipse/yasson/internal/serializer/SerializerBuilder.java
index 7262cef..5731d79 100644
--- a/src/main/java/org/eclipse/yasson/internal/serializer/SerializerBuilder.java
+++ b/src/main/java/org/eclipse/yasson/internal/serializer/SerializerBuilder.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 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.
@@ -10,7 +10,6 @@
* Contributors:
* Roman Grigoriadi
******************************************************************************/
-
package org.eclipse.yasson.internal.serializer;
import org.eclipse.yasson.internal.ComponentMatcher;
@@ -76,7 +75,7 @@
}
//Second user components is registered.
- Optional<AdapterBinding> adapterInfoOptional = componentMatcher.getAdapterBinding(getRuntimeType(), customization);
+ Optional<AdapterBinding> adapterInfoOptional = componentMatcher.getSerializeAdapterBinding(getRuntimeType(), customization);
if (adapterInfoOptional.isPresent()) {
return new AdaptedObjectSerializer<>(classModel, adapterInfoOptional.get());
}
diff --git a/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java b/src/test/java/org/eclipse/yasson/adapters/AdaptersTest.java
index 17676ad..9ae2b66 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, 2018 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019 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.
@@ -37,13 +37,16 @@
import javax.json.bind.adapter.JsonbAdapter;
import java.lang.reflect.Type;
import java.math.BigDecimal;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.UUID;
+import static java.util.Collections.unmodifiableMap;
import static org.junit.Assert.assertEquals;
/**
@@ -482,4 +485,96 @@
Assert.assertEquals(Integer.valueOf(10), pojo.getNumberInteger());
Assert.assertEquals(Integer.valueOf(11), pojo.getSerializableInteger());
}
+
+ public static class PropertyTypeMismatch {
+ private Throwable error = new RuntimeException("foo");
+
+ public Optional<Throwable> getError() {
+ return Optional.ofNullable(error);
+ }
+
+ public void setError(Instant errorTime) {
+ this.error = new RuntimeException("Error at: " + errorTime.toString());
+ }
+ }
+
+ public static class ThrowableAdapter implements JsonbAdapter<Throwable, Map<String, Object>> {
+
+ public int callCount = 0;
+
+ @Override
+ public Map<String, Object> adaptToJson(Throwable obj) throws Exception {
+ HashMap<String, Object> output = new HashMap<>();
+ output.put("message", obj.getMessage());
+ output.put("type", obj.getClass().getName());
+ callCount++;
+
+ return unmodifiableMap(output);
+ }
+
+ @Override
+ public Throwable adaptFromJson(Map<String, Object> obj) throws Exception {
+ throw new UnsupportedOperationException("not implemented");
+ }
+ }
+
+ /**
+ * Serialize a class that has mismatching properties. The field is of type
+ * Throwable but the getter method is of type Optional<Throwable>. The user-defined
+ * adapter for Throwable should still be called.
+ */
+ @Test
+ public void testOptionalAdapter() {
+ ThrowableAdapter adapter = new ThrowableAdapter();
+ jsonb = JsonbBuilder.newBuilder()
+ .withConfig(new JsonbConfig().withAdapters(adapter))
+ .build();
+
+ PropertyTypeMismatch obj = new PropertyTypeMismatch();
+ String json = jsonb.toJson(obj);
+ assertEquals("{\"error\":{\"message\":\"foo\",\"type\":\"java.lang.RuntimeException\"}}", json);
+ assertEquals("The user-defined ThrowableAdapter should have been called", 1, adapter.callCount);
+ }
+
+ public static class InstantAdapter implements JsonbAdapter<Instant, String> {
+
+ public int callCount = 0;
+
+ @Override
+ public String adaptToJson(Instant obj) throws Exception {
+ return obj.toString();
+ }
+
+ @Override
+ public Instant adaptFromJson(String obj) throws Exception {
+ callCount++;
+ if (obj.equals("CUSTOM_VALUE"))
+ return Instant.MAX;
+ return Instant.parse(obj);
+ }
+ }
+
+ /**
+ * Make sure that the same property can use a different adapter for
+ * serialization and deserialization.
+ */
+ @Test
+ public void testDifferentAdapters() {
+ ThrowableAdapter throwableAdapter = new ThrowableAdapter();
+ InstantAdapter instantAdapter = new InstantAdapter();
+ jsonb = JsonbBuilder.newBuilder()
+ .withConfig(new JsonbConfig().withAdapters(throwableAdapter, instantAdapter))
+ .build();
+
+ String json = "{\"error\":\"CUSTOM_VALUE\"}";
+ PropertyTypeMismatch obj = jsonb.fromJson(json, PropertyTypeMismatch.class);
+ assertEquals("Error at: +1000000000-12-31T23:59:59.999999999Z", obj.getError().get().getMessage());
+ assertEquals(1, instantAdapter.callCount);
+
+ String afterJson = jsonb.toJson(obj);
+ assertEquals("{\"error\":{\"message\":\"Error at: +1000000000-12-31T23:59:59.999999999Z\",\"type\":\"java.lang.RuntimeException\"}}",
+ afterJson);
+ assertEquals(1, throwableAdapter.callCount);
+ }
+
}
diff --git a/src/test/java/org/eclipse/yasson/defaultmapping/basic/PropertyMismatchTest.java b/src/test/java/org/eclipse/yasson/defaultmapping/basic/PropertyMismatchTest.java
index eccdbaa..4a177c4 100644
--- a/src/test/java/org/eclipse/yasson/defaultmapping/basic/PropertyMismatchTest.java
+++ b/src/test/java/org/eclipse/yasson/defaultmapping/basic/PropertyMismatchTest.java
@@ -1,12 +1,24 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2019 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.defaultmapping.basic;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import java.time.Instant;
import java.util.HashMap;
import java.util.HashSet;
+import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
+import javax.json.bind.annotation.JsonbTransient;
import org.jboss.weld.exceptions.IllegalStateException;
import org.junit.Test;
@@ -101,4 +113,38 @@
String json = JsonbBuilder.create().toJson(obj);
assertEquals("{}", json);
}
+
+ public static class PropertyTypeMismatch {
+ @JsonbTransient
+ public Instant internalInstantProperty;
+
+ private String foo;
+ public int getFoo() {
+ return foo.length();
+ }
+ public void setFoo(Instant instant) {
+ this.foo = instant.toString();
+ this.internalInstantProperty = instant;
+ }
+ }
+
+ /**
+ * Test that properties of the same name with different
+ * field/getter/setter types behave properly and that we don't
+ * assume they are all equal
+ */
+ @Test
+ public void testPropertyTypesMismatch() {
+ PropertyTypeMismatch obj = new PropertyTypeMismatch();
+ Instant now = Instant.now();
+ obj.setFoo(now);
+
+ Jsonb jsonb = JsonbBuilder.create();
+ String json = jsonb.toJson(obj);
+ assertEquals("{\"foo\":" + now.toString().length() + "}", json);
+
+ PropertyTypeMismatch after = jsonb.fromJson("{\"foo\":\"" + now.toString() + "\"}", PropertyTypeMismatch.class);
+ assertEquals(obj.getFoo(), after.getFoo());
+ assertEquals(obj.internalInstantProperty, after.internalInstantProperty);
+ }
}