This is an automated email from the ASF dual-hosted git repository.

rmannibucau pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/johnzon.git

commit 0775ac035f0e98d1f768418b619d47932840384d
Author: Romain Manni-Bucau <[email protected]>
AuthorDate: Sat Aug 10 17:20:39 2019 +0200

    JOHNZON-238 JOHNZON-237 ensure to read class annotation on the superclass + 
respect deserialization order based on the json and not the class (spec 
requirement we can challenge later)
---
 .../org/apache/johnzon/jsonb/JsonbAccessMode.java  |  38 ++--
 .../apache/johnzon/jsonb/DefaultMappingTest.java   |   7 +-
 .../java/org/apache/johnzon/jsonb/OrderTest.java   | 196 +++++++--------------
 .../org/apache/johnzon/jsonb/SerializerTest.java   | 150 ++++++++++++++++
 .../apache/johnzon/mapper/MappingParserImpl.java   |  16 +-
 .../org/apache/johnzon/mapper/access/Meta.java     |  22 ++-
 pom.xml                                            |   3 +-
 7 files changed, 271 insertions(+), 161 deletions(-)

diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
index c08d529..87819ca 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
@@ -781,16 +781,18 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
         private ObjectConverter.Reader reader;
 
         ReaderConverters(final DecoratedType annotationHolder) {
+            final boolean numberType = 
isNumberType(annotationHolder.getType());
+            final boolean dateType = isDateType(annotationHolder.getType());
             final JsonbTypeDeserializer deserializer = 
annotationHolder.getAnnotation(JsonbTypeDeserializer.class);
             final JsonbTypeAdapter adapter = 
annotationHolder.getAnnotation(JsonbTypeAdapter.class);
-            JsonbDateFormat dateFormat = 
annotationHolder.getAnnotation(JsonbDateFormat.class);
-            JsonbNumberFormat numberFormat = 
annotationHolder.getAnnotation(JsonbNumberFormat.class);
+            JsonbDateFormat dateFormat = dateType ? 
annotationHolder.getAnnotation(JsonbDateFormat.class) : null;
+            JsonbNumberFormat numberFormat = numberType ? 
annotationHolder.getAnnotation(JsonbNumberFormat.class) : null;
             final JohnzonConverter johnzonConverter = 
annotationHolder.getAnnotation(JohnzonConverter.class);
             validateAnnotations(annotationHolder, adapter, dateFormat, 
numberFormat, johnzonConverter);
-            if (dateFormat == null && isDateType(annotationHolder.getType())) {
+            if (dateFormat == null && dateType) {
                 dateFormat = 
annotationHolder.getClassOrPackageAnnotation(JsonbDateFormat.class);
             }
-            if (numberFormat == null && 
isNumberType(annotationHolder.getType())) {
+            if (numberFormat == null && numberType) {
                 numberFormat = 
annotationHolder.getClassOrPackageAnnotation(JsonbNumberFormat.class);
             }
 
@@ -869,23 +871,25 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
         private Adapter<?, ?> converter;
         private ObjectConverter.Writer writer;
 
-        WriterConverters(final DecoratedType initialReader, final Types types) 
{
-            final JsonbTypeSerializer serializer = 
initialReader.getAnnotation(JsonbTypeSerializer.class);
-            final JsonbTypeAdapter adapter = 
initialReader.getAnnotation(JsonbTypeAdapter.class);
-            JsonbDateFormat dateFormat = 
initialReader.getAnnotation(JsonbDateFormat.class);
-            JsonbNumberFormat numberFormat = 
initialReader.getAnnotation(JsonbNumberFormat.class);
-            final JohnzonConverter johnzonConverter = 
initialReader.getAnnotation(JohnzonConverter.class);
-            validateAnnotations(initialReader, adapter, dateFormat, 
numberFormat, johnzonConverter);
-            if (dateFormat == null && isDateType(initialReader.getType())) {
-                dateFormat = 
initialReader.getClassOrPackageAnnotation(JsonbDateFormat.class);
+        WriterConverters(final DecoratedType reader, final Types types) {
+            final boolean numberType = isNumberType(reader.getType());
+            final boolean dateType = isDateType(reader.getType());
+            final JsonbTypeSerializer serializer = 
reader.getAnnotation(JsonbTypeSerializer.class);
+            final JsonbTypeAdapter adapter = 
reader.getAnnotation(JsonbTypeAdapter.class);
+            JsonbDateFormat dateFormat = dateType ? 
reader.getAnnotation(JsonbDateFormat.class) : null;
+            JsonbNumberFormat numberFormat = numberType ? 
reader.getAnnotation(JsonbNumberFormat.class) : null;
+            final JohnzonConverter johnzonConverter = 
reader.getAnnotation(JohnzonConverter.class);
+            validateAnnotations(reader, adapter, dateFormat, numberFormat, 
johnzonConverter);
+            if (dateFormat == null && isDateType(reader.getType())) {
+                dateFormat = 
reader.getClassOrPackageAnnotation(JsonbDateFormat.class);
             }
-            if (numberFormat == null && isNumberType(initialReader.getType())) 
{
-                numberFormat = 
initialReader.getClassOrPackageAnnotation(JsonbNumberFormat.class);
+            if (numberFormat == null && isNumberType(reader.getType())) {
+                numberFormat = 
reader.getClassOrPackageAnnotation(JsonbNumberFormat.class);
             }
 
             converter = adapter == null && dateFormat == null && numberFormat 
== null && johnzonConverter == null ?
-                    defaultConverters.get(new 
AdapterKey(initialReader.getType(), String.class)) :
-                    toConverter(types, initialReader.getType(), adapter, 
dateFormat, numberFormat);
+                    defaultConverters.get(new AdapterKey(reader.getType(), 
String.class)) :
+                    toConverter(types, reader.getType(), adapter, dateFormat, 
numberFormat);
 
             if (serializer != null) {
                 final Class<? extends JsonbSerializer> value = 
serializer.value();
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java
index 0d92a32..e707663 100644
--- 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java
@@ -1067,10 +1067,11 @@ public class DefaultMappingTest {
         
assertEquals("{\"aField\":\"aField\",\"aa\":\"aa\",\"bField\":\"bField\",\"bb\":\"bb\",\"cField\":\"cField\",\"cc\":\"cc\"}",
             JSONB.toJson(attributesOrderingWithInheritance));
 
+        // important, see OrderTest#deserializationRespectsOrderToo
         AttributesOrderingWithCounterClass attributesOrderingWithCounterClass 
= JSONB.fromJson("{\"second\":\"a\",\"third\":\"b\",\"first\":\"c\"}", 
AttributesOrderingWithCounterClass.class);
-        assertEquals("a1", attributesOrderingWithCounterClass.second);
-        assertEquals("b2", attributesOrderingWithCounterClass.third);
-        assertEquals("c0", attributesOrderingWithCounterClass.first);
+        assertEquals("a0", attributesOrderingWithCounterClass.second);
+        assertEquals("b1", attributesOrderingWithCounterClass.third);
+        assertEquals("c2", attributesOrderingWithCounterClass.first);
     }
 
     public static void toJsonNullValues() {
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/OrderTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/OrderTest.java
index 355032d..a2630d3 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/OrderTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/OrderTest.java
@@ -21,21 +21,8 @@ package org.apache.johnzon.jsonb;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
-import java.lang.reflect.Type;
-import java.util.LinkedList;
-import java.util.List;
-
 import javax.json.bind.annotation.JsonbPropertyOrder;
-import javax.json.bind.annotation.JsonbTypeDeserializer;
-import javax.json.bind.annotation.JsonbTypeSerializer;
-import javax.json.bind.serializer.DeserializationContext;
-import javax.json.bind.serializer.JsonbDeserializer;
-import javax.json.bind.serializer.JsonbSerializer;
-import javax.json.bind.serializer.SerializationContext;
-import javax.json.stream.JsonGenerator;
-import javax.json.stream.JsonParser;
-
-import org.apache.johnzon.jsonb.model.Holder;
+
 import org.apache.johnzon.jsonb.test.JsonbRule;
 import org.junit.Rule;
 import org.junit.Test;
@@ -51,147 +38,96 @@ public class OrderTest {
                 
"\\{\\s*\"third\"\\s*:\\s*\"Third\"\\s*,\\s*\"fourth\"\\s*:\\s*\"Fourth\".*}"));
     }
 
-    @Test
-    public void typeSerializer() {
-        final HolderHolder container = new HolderHolder();
-        final StringHolder instance = new StringHolder();
-        instance.setInstance("Test String");
-        container.setInstance(instance);
-
-        final String json = jsonb.toJson(container);
-        assertTrue(json, json.matches(
-                
"\\{\\s*\"instance\"\\s*:\\s*\\{\\s*\"instance\"\\s*:\\s*\"Test String 
Serialized\"\\s*}\\s*}"));
-
-        final HolderHolder unmarshalledObject = jsonb.fromJson("{ \"instance\" 
: { \"instance\" : \"Test String\" } }", HolderHolder.class);
-        assertEquals("Test String Deserialized", 
unmarshalledObject.getInstance().getInstance());
+    @Test // TODO: not sure it is good to respect json and not mapping, we can 
challenge the spec on it
+    public void deserializationRespectsOrderToo() {
+        final String json = this.jsonb.toJson(new PartialOrder() {{ 
setStringInstance("Test String"); }});
+        
assertEquals("{\"longInstance\":0,\"intInstance\":0,\"stringInstance\":\"Test 
String\",\"anIntInstance\":0,\"anotherIntInstance\":0,\"yetAnotherIntInstance\":0}",
 json);
+        assertTrue(json, json.contains("anotherIntInstance"));
+        assertTrue(json, json.contains("anIntInstance"));
+        assertTrue(json, json.contains("yetAnotherIntInstance"));
+
+        final PartialOrder unmarshalledObject = jsonb.fromJson(
+                "{ \"anIntInstance\" : 100, \"yetAnotherIntInstance\":100, 
\"anotherIntInstance\": 100, " +
+                        "\"intInstance\" : 1, \"stringInstance\" : \"Test 
String\", \"longInstance\" : 0 }",
+                PartialOrder.class);
+        assertEquals(3, unmarshalledObject.getIntInstance());
+        assertEquals(100, unmarshalledObject.getAnotherIntInstance());
+        assertEquals(100, unmarshalledObject.getYetAnotherIntInstance());
+        assertEquals(100, unmarshalledObject.getAnIntInstance());
     }
 
-    @Test
-    public void arrayTypes() {
-        final ArrayHolder container = new ArrayHolder();
-        final StringHolder instance1 = new StringHolder();
-        instance1.setInstance("Test String 1");
-        final StringHolder instance2 = new StringHolder();
-        instance2.setInstance("Test String 2");
-        container.setInstance(new StringHolder[] { instance1, instance2 });
-
-        final String json = jsonb.toJson(container);
-        assertEquals("{\"instance\":[{\"instance\":\"Test String 
1\"},{\"instance\":\"Test String 2\"}]}", json);
-
-        final ArrayHolder unmarshalledObject = jsonb.fromJson(
-                "{ \"instance\" : [ { \"instance\" : \"Test String 1\" }, { 
\"instance\" : \"Test String 2\" } ] }",
-                ArrayHolder.class);
-        assertEquals("Test String 1", 
unmarshalledObject.getInstance()[0].getInstance());
-    }
+    @JsonbPropertyOrder({ "longInstance", "intInstance", "stringInstance" })
+    public static class PartialOrder {
+        private int intInstance;
 
-    public static class StringHolder implements Holder<String> {
-        private String instance = "Test";
+        private String stringInstance;
 
-        public String getInstance() {
-            return instance;
-        }
+        private long longInstance;
 
-        public void setInstance(final String instance) {
-            this.instance = instance;
+        private int anIntInstance;
+
+        private int anotherIntInstance;
+
+        private int yetAnotherIntInstance;
+
+        public int getAnIntInstance() {
+            intInstance -= 10;
+            return anIntInstance;
         }
-    }
 
-    public static class SimpleContainerDeserializer implements 
JsonbDeserializer<StringHolder> {
-        @Override
-        public StringHolder deserialize(final JsonParser parser, final 
DeserializationContext ctx, final Type type) {
-            final StringHolder container = new StringHolder();
-
-            while (parser.hasNext()) {
-                final JsonParser.Event event = parser.next();
-                if (event == JsonParser.Event.START_OBJECT) {
-                    continue;
-                }
-                if (event == JsonParser.Event.END_OBJECT) {
-                    break;
-                }
-                if (event == JsonParser.Event.KEY_NAME && 
"instance".equals(parser.getString())) {
-                    container.setInstance(ctx.deserialize(String.class, 
parser) + " Deserialized");
-                }
-            }
+        public void setAnIntInstance(int anIntInstance) {
+            intInstance -= 30;
+            this.anIntInstance = anIntInstance;
+        }
 
-            return container;
+        public int getAnotherIntInstance() {
+            intInstance -= 100;
+            return anotherIntInstance;
         }
-    }
 
-    public static class SimpleContainerSerializer implements 
JsonbSerializer<StringHolder> {
-        @Override
-        public void serialize(final StringHolder container, final 
JsonGenerator generator,
-                              final SerializationContext ctx) {
-            generator.writeStartObject();
-            ctx.serialize("instance", container.getInstance() + " Serialized", 
generator);
-            generator.writeEnd();
+        public void setAnotherIntInstance(int anotherIntInstance) {
+            intInstance -= 300;
+            this.anotherIntInstance = anotherIntInstance;
         }
-    }
 
-    public static class HolderHolder implements Holder<StringHolder> {
-        @JsonbTypeSerializer(SimpleContainerSerializer.class)
-        @JsonbTypeDeserializer(SimpleContainerDeserializer.class)
-        private StringHolder instance;
+        public int getYetAnotherIntInstance() {
+            intInstance -= 1000;
+            return yetAnotherIntInstance;
+        }
 
-        @Override
-        public StringHolder getInstance() {
-            return instance;
+        public void setYetAnotherIntInstance(int yetAnotherIntInstance) {
+            intInstance -= 3000;
+            this.yetAnotherIntInstance = yetAnotherIntInstance;
         }
 
-        @Override
-        public void setInstance(StringHolder instance) {
-            this.instance = instance;
+        public String getStringInstance() {
+            return stringInstance;
         }
-    }
 
-    public static class ArrayHolder implements Holder<StringHolder[]> {
-        @JsonbTypeSerializer(StringArraySerializer.class)
-        @JsonbTypeDeserializer(StringArrayDeserializer.class)
-        private StringHolder[] instance;
+        public void setStringInstance(String stringInstance) {
+            this.stringInstance = stringInstance;
+            if (intInstance == 1) {
+                intInstance = 2;
+            }
+        }
 
-        @Override
-        public StringHolder[] getInstance() {
-            return instance;
+        public int getIntInstance() {
+            return intInstance;
         }
 
-        @Override
-        public void setInstance(final StringHolder[] instance) {
-            this.instance = instance;
+        public void setIntInstance(int intInstance) {
+            this.intInstance = intInstance;
         }
-    }
 
-    public static class StringArraySerializer implements 
JsonbSerializer<StringHolder[]> {
-        @Override
-        public void serialize(final StringHolder[] containers,
-                              final JsonGenerator jsonGenerator,
-                              final SerializationContext serializationContext) 
{
-            jsonGenerator.writeStartArray();
-            for (final StringHolder container : containers) {
-                serializationContext.serialize(container, jsonGenerator);
-            }
-            jsonGenerator.writeEnd();
+        public long getLongInstance() {
+            return longInstance;
         }
-    }
 
-    public static class StringArrayDeserializer implements 
JsonbDeserializer<StringHolder[]> {
-        @Override
-        public StringHolder[] deserialize(final JsonParser jsonParser,
-                                          final DeserializationContext 
deserializationContext,
-                                          final Type type) {
-            final List<StringHolder> containers = new LinkedList<>();
-
-            while (jsonParser.hasNext()) {
-                JsonParser.Event event = jsonParser.next();
-                if (event == JsonParser.Event.START_OBJECT) {
-                    containers.add(deserializationContext.deserialize(
-                            new StringHolder() 
{}.getClass().getGenericSuperclass(), jsonParser));
-                }
-                if (event == JsonParser.Event.END_OBJECT) {
-                    break;
-                }
+        public void setLongInstance(long longInstance) {
+            this.longInstance = longInstance;
+            if (intInstance == 2) {
+                intInstance = 3;
             }
-
-            return containers.toArray(new StringHolder[0]);
         }
     }
 
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java
index 2bd6f38..7945835 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.assertTrue;
 
 import java.lang.reflect.Type;
 import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -41,9 +42,48 @@ import javax.json.bind.serializer.SerializationContext;
 import javax.json.stream.JsonGenerator;
 import javax.json.stream.JsonParser;
 
+import org.apache.johnzon.jsonb.model.Holder;
+import org.apache.johnzon.jsonb.test.JsonbRule;
+import org.junit.Rule;
 import org.junit.Test;
 
 public class SerializerTest {
+    @Rule
+    public final JsonbRule jsonb = new JsonbRule();
+
+    @Test
+    public void typeSerializer() {
+        final HolderHolder container = new HolderHolder();
+        final StringHolder instance = new StringHolder();
+        instance.setInstance("Test String");
+        container.setInstance(instance);
+
+        final String json = jsonb.toJson(container);
+        assertTrue(json, json.matches(
+                
"\\{\\s*\"instance\"\\s*:\\s*\\{\\s*\"instance\"\\s*:\\s*\"Test String 
Serialized\"\\s*}\\s*}"));
+
+        final HolderHolder unmarshalledObject = jsonb.fromJson("{ \"instance\" 
: { \"instance\" : \"Test String\" } }", HolderHolder.class);
+        assertEquals("Test String Deserialized", 
unmarshalledObject.getInstance().getInstance());
+    }
+
+    @Test
+    public void arrayTypes() {
+        final ArrayHolder container = new ArrayHolder();
+        final StringHolder instance1 = new StringHolder();
+        instance1.setInstance("Test String 1");
+        final StringHolder instance2 = new StringHolder();
+        instance2.setInstance("Test String 2");
+        container.setInstance(new StringHolder[] { instance1, instance2 });
+
+        final String json = jsonb.toJson(container);
+        assertEquals("{\"instance\":[{\"instance\":\"Test String 
1\"},{\"instance\":\"Test String 2\"}]}", json);
+
+        final ArrayHolder unmarshalledObject = jsonb.fromJson(
+                "{ \"instance\" : [ { \"instance\" : \"Test String 1\" }, { 
\"instance\" : \"Test String 2\" } ] }",
+                ArrayHolder.class);
+        assertEquals("Test String 1", 
unmarshalledObject.getInstance()[0].getInstance());
+    }
+
 
     @Test
     public void roundTrip() {
@@ -131,6 +171,116 @@ public class SerializerTest {
         jsonb.close();
     }
 
+    public static class StringHolder implements Holder<String> {
+        private String instance = "Test";
+
+        public String getInstance() {
+            return instance;
+        }
+
+        public void setInstance(final String instance) {
+            this.instance = instance;
+        }
+    }
+
+    public static class SimpleContainerDeserializer implements 
JsonbDeserializer<StringHolder> {
+        @Override
+        public StringHolder deserialize(final JsonParser parser, final 
DeserializationContext ctx, final Type type) {
+            final StringHolder container = new StringHolder();
+
+            while (parser.hasNext()) {
+                final JsonParser.Event event = parser.next();
+                if (event == JsonParser.Event.START_OBJECT) {
+                    continue;
+                }
+                if (event == JsonParser.Event.END_OBJECT) {
+                    break;
+                }
+                if (event == JsonParser.Event.KEY_NAME && 
"instance".equals(parser.getString())) {
+                    container.setInstance(ctx.deserialize(String.class, 
parser) + " Deserialized");
+                }
+            }
+
+            return container;
+        }
+    }
+
+    public static class SimpleContainerSerializer implements 
JsonbSerializer<StringHolder> {
+        @Override
+        public void serialize(final StringHolder container, final 
JsonGenerator generator,
+                              final SerializationContext ctx) {
+            generator.writeStartObject();
+            ctx.serialize("instance", container.getInstance() + " Serialized", 
generator);
+            generator.writeEnd();
+        }
+    }
+
+    public static class HolderHolder implements Holder<StringHolder> {
+        @JsonbTypeSerializer(SimpleContainerSerializer.class)
+        @JsonbTypeDeserializer(SimpleContainerDeserializer.class)
+        private StringHolder instance;
+
+        @Override
+        public StringHolder getInstance() {
+            return instance;
+        }
+
+        @Override
+        public void setInstance(StringHolder instance) {
+            this.instance = instance;
+        }
+    }
+
+    public static class ArrayHolder implements Holder<StringHolder[]> {
+        @JsonbTypeSerializer(StringArraySerializer.class)
+        @JsonbTypeDeserializer(StringArrayDeserializer.class)
+        private StringHolder[] instance;
+
+        @Override
+        public StringHolder[] getInstance() {
+            return instance;
+        }
+
+        @Override
+        public void setInstance(final StringHolder[] instance) {
+            this.instance = instance;
+        }
+    }
+
+    public static class StringArraySerializer implements 
JsonbSerializer<StringHolder[]> {
+        @Override
+        public void serialize(final StringHolder[] containers,
+                              final JsonGenerator jsonGenerator,
+                              final SerializationContext serializationContext) 
{
+            jsonGenerator.writeStartArray();
+            for (final StringHolder container : containers) {
+                serializationContext.serialize(container, jsonGenerator);
+            }
+            jsonGenerator.writeEnd();
+        }
+    }
+
+    public static class StringArrayDeserializer implements 
JsonbDeserializer<StringHolder[]> {
+        @Override
+        public StringHolder[] deserialize(final JsonParser jsonParser,
+                                          final DeserializationContext 
deserializationContext,
+                                          final Type type) {
+            final List<StringHolder> containers = new LinkedList<>();
+
+            while (jsonParser.hasNext()) {
+                JsonParser.Event event = jsonParser.next();
+                if (event == JsonParser.Event.START_OBJECT) {
+                    containers.add(deserializationContext.deserialize(
+                            new StringHolder() 
{}.getClass().getGenericSuperclass(), jsonParser));
+                }
+                if (event == JsonParser.Event.END_OBJECT) {
+                    break;
+                }
+            }
+
+            return containers.toArray(new StringHolder[0]);
+        }
+    }
 
     public static class Foo {
         public String name;
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
index 0068880..886f29a 100644
--- 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
@@ -334,13 +334,17 @@ public class MappingParserImpl implements MappingParser {
             jsonPointers.put(jsonPointer.toString(), t);
         }
 
-        for (final Map.Entry<String, Mappings.Setter> setter : 
classMapping.setters.entrySet()) {
-            final JsonValue jsonValue = object.get(setter.getKey());
+        for (final Map.Entry<String, JsonValue> jsonEntry : object.entrySet()) 
{
+            final Mappings.Setter value = 
classMapping.setters.get(jsonEntry.getKey());
+            if (value == null) {
+                continue;
+            }
+
+            final JsonValue jsonValue = jsonEntry.getValue();
             final JsonValue.ValueType valueType = jsonValue != null ? 
jsonValue.getValueType() : null;
 
-            final Mappings.Setter value = setter.getValue();
             if (JsonValue.class == value.paramType) {
-                setter.getValue().writer.write(t, jsonValue);
+                value.writer.write(t, jsonValue);
                 continue;
             }
             if (jsonValue == null) {
@@ -353,7 +357,7 @@ public class MappingParserImpl implements MappingParser {
             } else {
                 Object existingInstance = null;
                 if (config.isReadAttributeBeforeWrite()) {
-                    final Mappings.Getter getter = 
classMapping.getters.get(setter.getKey());
+                    final Mappings.Getter getter = 
classMapping.getters.get(jsonEntry.getKey());
                     if (getter != null) {
                         try {
                             existingInstance = getter.reader.read(t);
@@ -365,7 +369,7 @@ public class MappingParserImpl implements MappingParser {
                 final Object convertedValue = toValue(
                         existingInstance, jsonValue, value.converter, 
value.itemConverter,
                         value.paramType, value.objectConverter,
-                        new JsonPointerTracker(jsonPointer, setter.getKey()), 
inType);
+                        new JsonPointerTracker(jsonPointer, 
jsonEntry.getKey()), inType);
                 if (convertedValue != null) {
                     setterMethod.write(t, convertedValue);
                 }
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/Meta.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/Meta.java
index dbf8e00..97cfab1 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/Meta.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/Meta.java
@@ -27,7 +27,9 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Supplier;
 
 public final class Meta {
@@ -81,11 +83,23 @@ public final class Meta {
     }
 
     public static <T extends Annotation> T getAnnotation(final Class<?> clazz, 
final Class<T> api) {
-        final T annotation = clazz.getAnnotation(api);
-        if (annotation != null) {
-            return annotation;
+        Class<?> current = clazz;
+        final Set<Class<?>> visited = new HashSet<>();
+        while (current != null && current != Object.class) {
+            if (!visited.add(current)) {
+                return null;
+            }
+            final T annotation = current.getAnnotation(api);
+            if (annotation != null) {
+                return annotation;
+            }
+            final T meta = findMeta(clazz.getAnnotations(), api);
+            if (meta != null) {
+                return meta;
+            }
+            current = current.getSuperclass();
         }
-        return findMeta(clazz.getAnnotations(), api);
+        return null;
     }
 
     public static <T extends Annotation> T getAnnotation(final Package pck, 
final Class<T> api) {
diff --git a/pom.xml b/pom.xml
index 3f26909..7b77653 100644
--- a/pom.xml
+++ b/pom.xml
@@ -313,9 +313,10 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
-        <version>2.19.1</version>
+        <version>3.0.0-M3</version>
         <configuration>
           <argLine>${surefire.jvm.params}</argLine>
+          <trimStackTrace>false</trimStackTrace>
         </configuration>
       </plugin>
 

Reply via email to