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

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


The following commit(s) were added to refs/heads/master by this push:
     new b4a25a4  JOHNZON-226 get mostly rid of j.l.r.Arrays
b4a25a4 is described below

commit b4a25a4b7301fb7f44e1c7266b0e42c671a0b606
Author: Mark Struberg <[email protected]>
AuthorDate: Wed Jul 31 19:09:14 2019 +0200

    JOHNZON-226 get mostly rid of j.l.r.Arrays
    
    java.lang.reflect.Array operations are known to be expensive.
    So it's best to avoid them alltogether.
    This small hack improved performance for array handling for about 50%.
---
 .../apache/johnzon/core/JsonArrayBuilderImpl.java  |   7 +-
 .../apache/johnzon/core/JsonObjectBuilderImpl.java |  10 +-
 .../org/apache/johnzon/core/util/ArrayUtil.java    | 111 ++--
 .../org/apache/johnzon/jsonb/JohnzonJsonb.java     |  29 +-
 .../apache/johnzon/jsonb/DefaultMappingTest.java   |   4 +
 .../johnzon/jsonb/SeriaizersRoundTripTest.java     | 282 ----------
 .../johnzon/jsonb/SerializersRoundTripTest.java    | 571 +++++++++++++++++++++
 .../java/org/apache/johnzon/mapper/Mapper.java     |   6 +-
 .../johnzon/mapper/MappingGeneratorImpl.java       |   5 +-
 .../apache/johnzon/mapper/MappingParserImpl.java   | 165 ++++++
 .../org/apache/johnzon/mapper}/util/ArrayUtil.java |  81 ++-
 11 files changed, 918 insertions(+), 353 deletions(-)

diff --git 
a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java 
b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
index effd30a..af2aa25 100644
--- 
a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
+++ 
b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
@@ -24,7 +24,6 @@ import javax.json.JsonException;
 import javax.json.JsonObjectBuilder;
 import javax.json.JsonValue;
 import java.io.Serializable;
-import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
@@ -225,11 +224,7 @@ class JsonArrayBuilderImpl implements JsonArrayBuilder, 
Serializable {
         } else if (value instanceof Collection) {
             add(new JsonArrayBuilderImpl(Collection.class.cast(value), 
bufferProvider).build());
         } else if (value.getClass().isArray()) {
-            final int length = ArrayUtil.getArrayLength(value);
-            final Collection<Object> collection = new ArrayList<>(length);
-            for (int i = 0; i < length; i++) {
-                collection.add(Array.get(value, i));
-            }
+            final Collection<Object> collection = 
ArrayUtil.newCollection(value);
             add(new JsonArrayBuilderImpl(collection, bufferProvider).build());
         } else {
             throw new JsonException("Illegal JSON type! type=" + 
value.getClass());
diff --git 
a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java 
b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
index b0e80ea..e34c007 100644
--- 
a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
+++ 
b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonObjectBuilderImpl.java
@@ -24,15 +24,15 @@ import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 import javax.json.JsonValue;
 import java.io.Serializable;
-import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.math.BigInteger;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
+import org.apache.johnzon.core.util.ArrayUtil;
+
 class JsonObjectBuilderImpl implements JsonObjectBuilder, Serializable {
     private BufferStrategy.BufferProvider<char[]> bufferProvider;
     private Map<String, JsonValue> attributeMap = new LinkedHashMap<>();
@@ -85,11 +85,7 @@ class JsonObjectBuilderImpl implements JsonObjectBuilder, 
Serializable {
         } else if (value instanceof Collection) {
             add(name, new JsonArrayBuilderImpl(Collection.class.cast(value), 
bufferProvider).build());
         } else if (value.getClass().isArray()) {
-            final int length = Array.getLength(value);
-            final Collection<Object> collection = new ArrayList<>(length);
-            for (int i = 0; i < length; i++) {
-                collection.add(Array.get(value, i));
-            }
+            final Collection<Object> collection = 
ArrayUtil.newCollection(value);
             add(name, new JsonArrayBuilderImpl(collection, 
bufferProvider).build());
         } else {
             throw new JsonException("Illegal JSON type! name=" + name + " 
type=" + value.getClass());
diff --git 
a/johnzon-core/src/main/java/org/apache/johnzon/core/util/ArrayUtil.java 
b/johnzon-core/src/main/java/org/apache/johnzon/core/util/ArrayUtil.java
index 646c112..22904d3 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/util/ArrayUtil.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/util/ArrayUtil.java
@@ -17,49 +17,20 @@
 package org.apache.johnzon.core.util;
 
 import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
- * Various Array utils which do not exist in Java.
+ * Various Array utils which do not exist in Java or are performing badly.
+ *
+ * NOTE: we keep this here and in Mapper duplicated to not have Mapper 
depending on johnzon-core!
  */
 public final class ArrayUtil {
     private ArrayUtil() {
         // utility class ct
     }
 
-    public static int getArrayLength(Object array) {
-        // Note: all types of multidimensional arrays are instanceof Object[]
-        if (array instanceof Object[]) {
-            return ((Object[]) array).length;
-        }
-        if (array instanceof boolean[]) {
-            return ((boolean[])array).length;
-        }
-        if (array instanceof byte[]) {
-            return ((byte[])array).length;
-        }
-        if (array instanceof char[]) {
-            return ((char[]) array).length;
-        }
-        if (array instanceof short[]) {
-            return ((short[]) array).length;
-        }
-        if (array instanceof int[]) {
-            return ((int[]) array).length;
-        }
-        if (array instanceof long[]) {
-            return ((long[]) array).length;
-        }
-        if (array instanceof float[]) {
-            return ((float[]) array).length;
-        }
-        if (array instanceof double[]) {
-            return ((double[]) array).length;
-        }
-
-        throw new IllegalArgumentException("This is not an array! " + array);
-    }
-
 
     public static List<Integer> asList(final int[] vals) {
         return new AbstractList<Integer>() {
@@ -159,5 +130,77 @@ public final class ArrayUtil {
         };
     }
 
+    public static List<Object> asList(final Object[] vals) {
+        return new AbstractList<Object>() {
+            @Override
+            public Object get(int index) {
+                return vals[index];
+            }
+
+            @Override
+            public int size() {
+                return vals.length;
+            }
+        };
+    }
+
+    /**
+     * Take the given array object and fill a fresh Collection with it.
+     * @throws IllegalArgumentException if the given value this is not an 
array.
+     */
+    public static Collection<Object> newCollection(Object array) {
+
+        // Note: all types of multidimensional arrays are instanceof Object[]
+        if (array instanceof Object[]) {
+            return asList(((Object[])array));
+        }
+
+        ArrayList<Object> collection;
+
+        if (array instanceof boolean[]) {
+            collection = new ArrayList<>(((boolean[])array).length);
+            for (boolean o : ((boolean[]) array)) {
+                collection.add(o);
+            }
+        } else if (array instanceof byte[]) {
+            collection = new ArrayList<>(((byte[])array).length);
+            for (byte o : ((byte[]) array)) {
+                collection.add(o);
+            }
+        } else if (array instanceof char[]) {
+            collection = new ArrayList<>(((char[])array).length);
+            for (char o : ((char[]) array)) {
+                collection.add(o);
+            }
+        } else if (array instanceof short[]) {
+            collection = new ArrayList<>(((short[])array).length);
+            for (short o : ((short[]) array)) {
+                collection.add(o);
+            }
+        } else if (array instanceof int[]) {
+            collection = new ArrayList<>(((int[])array).length);
+            for (int o : ((int[]) array)) {
+                collection.add(o);
+            }
+        } else if (array instanceof long[]) {
+            collection = new ArrayList<>(((long[])array).length);
+            for (long o : ((long[]) array)) {
+                collection.add(o);
+            }
+        } else if (array instanceof float[]) {
+            collection = new ArrayList<>(((float[])array).length);
+            for (float o : ((float[]) array)) {
+                collection.add(o);
+            }
+        } else if (array instanceof double[]) {
+            collection = new ArrayList<>(((double[])array).length);
+            for (double o : ((double[]) array)) {
+                collection.add(o);
+            }
+        } else {
+            throw new IllegalArgumentException("This is not an array! " + 
array);
+        }
 
+        return collection;
+    }
 }
diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java
index 7965519..c173bc4 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java
@@ -18,7 +18,7 @@
  */
 package org.apache.johnzon.jsonb;
 
-import org.apache.johnzon.core.util.ArrayUtil;
+import org.apache.johnzon.mapper.util.ArrayUtil;
 import org.apache.johnzon.jsonb.api.experimental.JsonbExtension;
 import org.apache.johnzon.jsonb.extension.JsonValueReader;
 import org.apache.johnzon.jsonb.extension.JsonValueWriter;
@@ -39,7 +39,6 @@ import java.io.OutputStream;
 import java.io.Reader;
 import java.io.StringReader;
 import java.io.Writer;
-import java.lang.reflect.Array;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.math.BigInteger;
@@ -258,43 +257,43 @@ public class JohnzonJsonb implements Jsonb, 
AutoCloseable, JsonbExtension {
             final int length = ArrayUtil.getArrayLength(object);
             array = new Integer[length];
             for (int i = 0; i < length; i++) {
-                array[i] = Array.getInt(object, i);
+                array[i] = ((int[])object)[i];
             }
         } else if (double.class == componentType) {
             final int length = ArrayUtil.getArrayLength(object);
-            array = new Integer[length];
+            array = new Double[length];
             for (int i = 0; i < length; i++) {
-                array[i] = Array.getDouble(object, i);
+                array[i] = ((double[])object)[i];
             }
         } else if (byte.class == componentType) {
             final int length = ArrayUtil.getArrayLength(object);
-            array = new Integer[length];
+            array = new Byte[length];
             for (int i = 0; i < length; i++) {
-                array[i] = Array.getByte(object, i);
+                array[i] = ((byte[])object)[i];
             }
         } else if (char.class == componentType) {
             final int length = ArrayUtil.getArrayLength(object);
-            array = new Integer[length];
+            array = new Character[length];
             for (int i = 0; i < length; i++) {
-                array[i] = Array.getChar(object, i);
+                array[i] = ((char[])object)[i];
             }
         } else if (float.class == componentType) {
             final int length = ArrayUtil.getArrayLength(object);
-            array = new Integer[length];
+            array = new Float[length];
             for (int i = 0; i < length; i++) {
-                array[i] = Array.getFloat(object, i);
+                array[i] = ((float[])object)[i];
             }
         } else if (long.class == componentType) {
             final int length = ArrayUtil.getArrayLength(object);
-            array = new Integer[length];
+            array = new Long[length];
             for (int i = 0; i < length; i++) {
-                array[i] = Array.getLong(object, i);
+                array[i] = ((long[])object)[i];
             }
         } else if (short.class == componentType) {
             final int length = ArrayUtil.getArrayLength(object);
-            array = new Integer[length];
+            array = new Short[length];
             for (int i = 0; i < length; i++) {
-                array[i] = Array.getShort(object, i);
+                array[i] = ((short[])object)[i];
             }
         } else {
             array = (Object[]) object;
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 d638d5a..0d92a32 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
@@ -523,6 +523,10 @@ public class DefaultMappingTest {
 
         assertEquals("[1,2,3]", JSONB.toJson(byteArray));
 
+        byte[] rbyteArray = {1, 2, 3};
+
+        assertEquals("[1,2,3]", JSONB.toJson(rbyteArray));
+
         Integer[] integerArray = {1, 2, 3};
 
         assertEquals("[1,2,3]", JSONB.toJson(integerArray));
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SeriaizersRoundTripTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SeriaizersRoundTripTest.java
deleted file mode 100644
index c87ab3a..0000000
--- 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SeriaizersRoundTripTest.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.johnzon.jsonb;
-
-import static org.junit.Assert.assertEquals;
-
-import java.lang.reflect.Type;
-import java.util.Objects;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
-import javax.json.JsonString;
-import javax.json.JsonValue;
-import javax.json.bind.Jsonb;
-import javax.json.bind.JsonbBuilder;
-import javax.json.bind.adapter.JsonbAdapter;
-import javax.json.bind.annotation.JsonbTypeAdapter;
-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.junit.Test;
-
-public class SeriaizersRoundTripTest {
-    
-    public enum Color {
-        
-        RED, GREEN, BLUE
-    }
-       
-    // Does not seem to work with enums
-    public static class Option {
-        
-        public static final Option YES = new Option(true);
-        public static final Option NO = new Option(false);
-        
-        private final boolean value;
-        
-        private Option(boolean value) {
-            this.value = value;
-        }
-
-        public boolean asBoolean() {
-            return value;
-        }
-        
-        public static Option of(boolean value) {
-            return value ? YES : NO;
-        }
-
-        @Override
-        public String toString() {
-            return "Option{value=" + value + '}';
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-            Option option = (Option) o;
-            return value == option.value;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(value);
-        }
-    }
-    
-    public static class VATNumber {
-        
-        private final long value;
-
-        public VATNumber(long value) {
-            this.value = value;
-        }
-        
-        public long getValue() {
-            return value;
-        }
-
-        @Override
-        public String toString() {
-            return "VATNumber{value=" + value + '}';
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-            VATNumber vatNumber = (VATNumber) o;
-            return value == vatNumber.value;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(value);
-        }
-    }
-    
-    public interface Composite<T, X> extends JsonbSerializer<T>, 
JsonbDeserializer<T>, JsonbAdapter<T, X> {}
-    
-    public static abstract class AbstractComposite<T, X> implements 
Composite<T, X> {}
-    
-    public static abstract class StringValueComposite<T> extends 
AbstractComposite<T, String> {}
-    
-    public static class UUIDComposite extends StringValueComposite<UUID> {
-        
-        public void serialize(UUID obj, JsonGenerator generator, 
SerializationContext ctx) {
-            generator.write(obj.toString());
-        }
-        
-        public UUID deserialize(JsonParser parser, DeserializationContext ctx, 
Type rtType) {
-            return UUID.fromString(parser.getString());
-        }
-
-        @Override
-        public UUID adaptFromJson(String obj) throws Exception {
-            return UUID.fromString(obj);
-        }
-        
-        @Override
-        public String adaptToJson(UUID obj) throws Exception {
-            return obj.toString();
-        }
-    }
-    
-    public static class OptionDeSer implements JsonbSerializer<Option>, 
JsonbDeserializer<Option> {
-
-        @Override
-        public Option deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
-            return Option.of(parser.getValue().equals(JsonValue.TRUE));
-        }
-
-        @Override
-        public void serialize(Option obj, JsonGenerator generator, 
SerializationContext ctx) {
-            generator.write(obj.asBoolean());
-        }
-    }
-    
-    public static class VATDeSer implements JsonbSerializer<VATNumber>, 
JsonbDeserializer<VATNumber> {
-
-        @Override
-        public VATNumber deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
-            return new VATNumber(parser.getLong());
-        }
-
-        @Override
-        public void serialize(VATNumber obj, JsonGenerator generator, 
SerializationContext ctx) {
-            generator.write(obj.getValue());
-        }
-    }
-    
-    public static class CharsDeSer implements JsonbSerializer<String>, 
JsonbDeserializer<String> {
-
-        @Override
-        public String deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
-            return 
parser.getArrayStream().map(JsonString.class::cast).map(JsonString::getString).collect(Collectors.joining());
-        }
-
-        @Override
-        public void serialize(String obj, JsonGenerator generator, 
SerializationContext ctx) {
-            generator.writeStartArray();
-            obj.chars().forEach(c -> generator.write(Character.toString((char) 
c)));
-            generator.writeEnd();
-        }
-    }
-    
-    public static class ColorDeSer implements JsonbSerializer<Color>, 
JsonbDeserializer<Color> {
-
-        @Override
-        public Color deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
-            switch (parser.getString()) {
-                case "R" : return Color.RED;
-                case "G" : return Color.GREEN;
-                case "B" : return Color.BLUE;
-                default : throw new IllegalArgumentException();
-            }
-        }
-
-        @Override
-        public void serialize(Color obj, JsonGenerator generator, 
SerializationContext ctx) {
-            generator.write(obj.name().substring(0,  1));
-        }
-    }
-
-    public static class Wrapper {
-        
-        @JsonbTypeSerializer(UUIDComposite.class)
-        @JsonbTypeDeserializer(UUIDComposite.class)
-        public UUID uuid;
-
-        @JsonbTypeAdapter(UUIDComposite.class)
-        public UUID uuid2;
-        
-        @JsonbTypeSerializer(OptionDeSer.class)
-        @JsonbTypeDeserializer(OptionDeSer.class)
-        public Option option;
-        
-        @JsonbTypeSerializer(VATDeSer.class)
-        @JsonbTypeDeserializer(VATDeSer.class)
-        public VATNumber vatNumber;
-
-        @JsonbTypeSerializer(CharsDeSer.class)
-        @JsonbTypeDeserializer(CharsDeSer.class)
-        public String hello;
-
-        @JsonbTypeSerializer(ColorDeSer.class)
-        @JsonbTypeDeserializer(ColorDeSer.class)
-        public Color color;
-
-        @Override
-        public String toString() {
-            return "Wrapper{uuid=" + uuid + ", uuid2=" + uuid2 + ", option=" + 
option +
-                    ", vatNumber=" + vatNumber + ", hello='" + hello + '\'' + 
", color=" + color + '}';
-        }
-
-        @Override
-        public boolean equals(final Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-            final Wrapper wrapper = (Wrapper) o;
-            return Objects.equals(uuid, wrapper.uuid) && Objects.equals(uuid2, 
wrapper.uuid2) && Objects.equals(option,
-                    wrapper.option) && Objects.equals(vatNumber, 
wrapper.vatNumber) && Objects.equals(hello,
-                    wrapper.hello) && color == wrapper.color;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(uuid, uuid2, option, vatNumber, hello, color);
-        }
-    }
-
-    @Test
-    public void roundTrip() throws Exception {
-        final Wrapper original = new Wrapper();
-        original.uuid = UUID.randomUUID();
-        original.uuid2 = UUID.randomUUID();
-        original.option = Option.YES;
-        original.vatNumber  = new VATNumber(42);
-        original.hello = "hello world";
-        original.color = Color.GREEN;
-
-        try (final Jsonb jsonb = JsonbBuilder.create()) {
-            final Wrapper deserialized = 
jsonb.fromJson(jsonb.toJson(original), Wrapper.class);
-            assertEquals(original, deserialized);
-        }
-    }
-}
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializersRoundTripTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializersRoundTripTest.java
new file mode 100644
index 0000000..e3b12bc
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializersRoundTripTest.java
@@ -0,0 +1,571 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.johnzon.jsonb;
+
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import javax.json.JsonString;
+import javax.json.JsonValue;
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.adapter.JsonbAdapter;
+import javax.json.bind.annotation.JsonbTypeAdapter;
+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.junit.Test;
+
+public class SerializersRoundTripTest {
+    
+    public enum Color {
+        
+        RED, GREEN, BLUE
+    }
+       
+    // Does not seem to work with enums
+    public static class Option {
+        
+        public static final Option YES = new Option(true);
+        public static final Option NO = new Option(false);
+        
+        private final boolean value;
+        
+        private Option(boolean value) {
+            this.value = value;
+        }
+
+        public boolean asBoolean() {
+            return value;
+        }
+        
+        public static Option of(boolean value) {
+            return value ? YES : NO;
+        }
+
+        @Override
+        public String toString() {
+            return "Option{value=" + value + '}';
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            Option option = (Option) o;
+            return value == option.value;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(value);
+        }
+    }
+    
+    public static class VATNumber {
+        
+        private final long value;
+
+        public VATNumber(long value) {
+            this.value = value;
+        }
+        
+        public long getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return "VATNumber{value=" + value + '}';
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            VATNumber vatNumber = (VATNumber) o;
+            return value == vatNumber.value;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(value);
+        }
+    }
+    
+    public interface Composite<T, X> extends JsonbSerializer<T>, 
JsonbDeserializer<T>, JsonbAdapter<T, X> {}
+    
+    public static abstract class AbstractComposite<T, X> implements 
Composite<T, X> {}
+    
+    public static abstract class StringValueComposite<T> extends 
AbstractComposite<T, String> {}
+    
+    public static class UUIDComposite extends StringValueComposite<UUID> {
+        
+        public void serialize(UUID obj, JsonGenerator generator, 
SerializationContext ctx) {
+            generator.write(obj.toString());
+        }
+        
+        public UUID deserialize(JsonParser parser, DeserializationContext ctx, 
Type rtType) {
+            return UUID.fromString(parser.getString());
+        }
+
+        @Override
+        public UUID adaptFromJson(String obj) throws Exception {
+            return UUID.fromString(obj);
+        }
+        
+        @Override
+        public String adaptToJson(UUID obj) throws Exception {
+            return obj.toString();
+        }
+    }
+    
+    public static class OptionDeSer implements JsonbSerializer<Option>, 
JsonbDeserializer<Option> {
+
+        @Override
+        public Option deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
+            return Option.of(parser.getValue().equals(JsonValue.TRUE));
+        }
+
+        @Override
+        public void serialize(Option obj, JsonGenerator generator, 
SerializationContext ctx) {
+            generator.write(obj.asBoolean());
+        }
+    }
+    
+    public static class VATDeSer implements JsonbSerializer<VATNumber>, 
JsonbDeserializer<VATNumber> {
+
+        @Override
+        public VATNumber deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
+            return new VATNumber(parser.getLong());
+        }
+
+        @Override
+        public void serialize(VATNumber obj, JsonGenerator generator, 
SerializationContext ctx) {
+            generator.write(obj.getValue());
+        }
+    }
+    
+    public static class CharsDeSer implements JsonbSerializer<String>, 
JsonbDeserializer<String> {
+
+        @Override
+        public String deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
+            return 
parser.getArrayStream().map(JsonString.class::cast).map(JsonString::getString).collect(Collectors.joining());
+        }
+
+        @Override
+        public void serialize(String obj, JsonGenerator generator, 
SerializationContext ctx) {
+            generator.writeStartArray();
+            obj.chars().forEach(c -> generator.write(Character.toString((char) 
c)));
+            generator.writeEnd();
+        }
+    }
+    
+    public static class ColorDeSer implements JsonbSerializer<Color>, 
JsonbDeserializer<Color> {
+
+        @Override
+        public Color deserialize(JsonParser parser, DeserializationContext 
ctx, Type rtType) {
+            switch (parser.getString()) {
+                case "R" : return Color.RED;
+                case "G" : return Color.GREEN;
+                case "B" : return Color.BLUE;
+                default : throw new IllegalArgumentException();
+            }
+        }
+
+        @Override
+        public void serialize(Color obj, JsonGenerator generator, 
SerializationContext ctx) {
+            generator.write(obj.name().substring(0,  1));
+        }
+    }
+
+    public static class Wrapper {
+        
+        @JsonbTypeSerializer(UUIDComposite.class)
+        @JsonbTypeDeserializer(UUIDComposite.class)
+        public UUID uuid;
+
+        @JsonbTypeAdapter(UUIDComposite.class)
+        public UUID uuid2;
+        
+        @JsonbTypeSerializer(OptionDeSer.class)
+        @JsonbTypeDeserializer(OptionDeSer.class)
+        public Option option;
+        
+        @JsonbTypeSerializer(VATDeSer.class)
+        @JsonbTypeDeserializer(VATDeSer.class)
+        public VATNumber vatNumber;
+
+        @JsonbTypeSerializer(CharsDeSer.class)
+        @JsonbTypeDeserializer(CharsDeSer.class)
+        public String hello;
+
+        @JsonbTypeSerializer(ColorDeSer.class)
+        @JsonbTypeDeserializer(ColorDeSer.class)
+        public Color color;
+
+        @Override
+        public String toString() {
+            return "Wrapper{uuid=" + uuid + ", uuid2=" + uuid2 + ", option=" + 
option +
+                    ", vatNumber=" + vatNumber + ", hello='" + hello + '\'' + 
", color=" + color + '}';
+        }
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            final Wrapper wrapper = (Wrapper) o;
+            return Objects.equals(uuid, wrapper.uuid) && Objects.equals(uuid2, 
wrapper.uuid2) && Objects.equals(option,
+                    wrapper.option) && Objects.equals(vatNumber, 
wrapper.vatNumber) && Objects.equals(hello,
+                    wrapper.hello) && color == wrapper.color;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(uuid, uuid2, option, vatNumber, hello, color);
+        }
+    }
+    
+    public static class ArrayContainer {
+        // native types
+        private boolean[] bboolean;
+        private byte[] bbyte;
+        private char[] bchar;
+        private short[] bshort;
+        private int[] bint;
+        private long[] blong;
+        private float[] bfloat;
+        private double[] bdouble;
+        
+        // string[]
+        private String[] bString;
+        
+        // wrapper types
+        private Boolean[] bWboolean;
+        private Byte[] bWbyte;
+        private Character[] bWchar;
+        private Short[] bWshort;
+        private Integer[] bWint;
+        private Long[] bWlong;
+        private Float[] bWfloat;
+        private Double[] bWdouble;
+
+        public boolean[] getBboolean() {
+            return bboolean;
+        }
+
+        public void setBboolean(boolean[] bboolean) {
+            this.bboolean = bboolean;
+        }
+
+        public byte[] getBbyte() {
+            return bbyte;
+        }
+
+        public void setBbyte(byte[] bbyte) {
+            this.bbyte = bbyte;
+        }
+
+        public char[] getBchar() {
+            return bchar;
+        }
+
+        public void setBchar(char[] bchar) {
+            this.bchar = bchar;
+        }
+
+        public short[] getBshort() {
+            return bshort;
+        }
+
+        public void setBshort(short[] bshort) {
+            this.bshort = bshort;
+        }
+
+        public int[] getBint() {
+            return bint;
+        }
+
+        public void setBint(int[] bint) {
+            this.bint = bint;
+        }
+
+        public long[] getBlong() {
+            return blong;
+        }
+
+        public void setBlong(long[] blong) {
+            this.blong = blong;
+        }
+
+        public float[] getBfloat() {
+            return bfloat;
+        }
+
+        public void setBfloat(float[] bfloat) {
+            this.bfloat = bfloat;
+        }
+
+        public double[] getBdouble() {
+            return bdouble;
+        }
+
+        public void setBdouble(double[] bdouble) {
+            this.bdouble = bdouble;
+        }
+
+        public String[] getbString() {
+            return bString;
+        }
+
+        public void setbString(String[] bString) {
+            this.bString = bString;
+        }
+
+        public Boolean[] getbWboolean() {
+            return bWboolean;
+        }
+
+        public void setbWboolean(Boolean[] bWboolean) {
+            this.bWboolean = bWboolean;
+        }
+
+        public Byte[] getbWbyte() {
+            return bWbyte;
+        }
+
+        public void setbWbyte(Byte[] bWbyte) {
+            this.bWbyte = bWbyte;
+        }
+
+        public Character[] getbWchar() {
+            return bWchar;
+        }
+
+        public void setbWchar(Character[] bWchar) {
+            this.bWchar = bWchar;
+        }
+
+        public Short[] getbWshort() {
+            return bWshort;
+        }
+
+        public void setbWshort(Short[] bWshort) {
+            this.bWshort = bWshort;
+        }
+
+        public Integer[] getbWint() {
+            return bWint;
+        }
+
+        public void setbWint(Integer[] bWint) {
+            this.bWint = bWint;
+        }
+
+        public Long[] getbWlong() {
+            return bWlong;
+        }
+
+        public void setbWlong(Long[] bWlong) {
+            this.bWlong = bWlong;
+        }
+
+        public Float[] getbWfloat() {
+            return bWfloat;
+        }
+
+        public void setbWfloat(Float[] bWfloat) {
+            this.bWfloat = bWfloat;
+        }
+
+        public Double[] getbWdouble() {
+            return bWdouble;
+        }
+
+        public void setbWdouble(Double[] bWdouble) {
+            this.bWdouble = bWdouble;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            ArrayContainer that = (ArrayContainer) o;
+
+            if (!Arrays.equals(bboolean, that.bboolean)) {
+                return false;
+            }
+            if (!Arrays.equals(bbyte, that.bbyte)) {
+                return false;
+            }
+            if (!Arrays.equals(bchar, that.bchar)) {
+                return false;
+            }
+            if (!Arrays.equals(bshort, that.bshort)) {
+                return false;
+            }
+            if (!Arrays.equals(bint, that.bint)) {
+                return false;
+            }
+            if (!Arrays.equals(blong, that.blong)) {
+                return false;
+            }
+            if (!Arrays.equals(bfloat, that.bfloat)) {
+                return false;
+            }
+            if (!Arrays.equals(bdouble, that.bdouble)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            if (!Arrays.equals(bString, that.bString)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            if (!Arrays.equals(bWboolean, that.bWboolean)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            if (!Arrays.equals(bWbyte, that.bWbyte)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            if (!Arrays.equals(bWchar, that.bWchar)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            if (!Arrays.equals(bWshort, that.bWshort)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            if (!Arrays.equals(bWint, that.bWint)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            if (!Arrays.equals(bWlong, that.bWlong)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            if (!Arrays.equals(bWfloat, that.bWfloat)) {
+                return false;
+            }
+            // Probably incorrect - comparing Object[] arrays with 
Arrays.equals
+            return Arrays.equals(bWdouble, that.bWdouble);
+        }
+
+        @Override
+        public int hashCode() {
+            int result = Arrays.hashCode(bboolean);
+            result = 31 * result + Arrays.hashCode(bbyte);
+            result = 31 * result + Arrays.hashCode(bchar);
+            result = 31 * result + Arrays.hashCode(bshort);
+            result = 31 * result + Arrays.hashCode(bint);
+            result = 31 * result + Arrays.hashCode(blong);
+            result = 31 * result + Arrays.hashCode(bfloat);
+            result = 31 * result + Arrays.hashCode(bdouble);
+            result = 31 * result + Arrays.hashCode(bString);
+            result = 31 * result + Arrays.hashCode(bWboolean);
+            result = 31 * result + Arrays.hashCode(bWbyte);
+            result = 31 * result + Arrays.hashCode(bWchar);
+            result = 31 * result + Arrays.hashCode(bWshort);
+            result = 31 * result + Arrays.hashCode(bWint);
+            result = 31 * result + Arrays.hashCode(bWlong);
+            result = 31 * result + Arrays.hashCode(bWfloat);
+            result = 31 * result + Arrays.hashCode(bWdouble);
+            return result;
+        }
+    }
+
+    @Test
+    public void testArrayRoundTrip() throws Exception {
+        ArrayContainer original = new ArrayContainer();
+        original.setBboolean(new boolean[]{true, false, true});
+        original.setbWboolean(new Boolean[]{true, false, true});
+        
+        original.setBbyte(new byte[]{0x00, 0x01, 0x02});
+        original.setbWbyte(new Byte[]{0x00, 0x01, 0x02});
+        
+        original.setBchar(new char[]{'a','b', 'c'});
+        original.setbWchar(new Character[]{'a','b', 'c'});
+
+        original.setBshort(new short[]{0, 1, 2});
+        original.setbWshort(new Short[]{0, 1, 2});
+
+        original.setBint(new int[]{0, 1, 2});
+        original.setbWint(new Integer[]{0, 1, 2});
+
+        original.setBlong(new long[]{0L, 1L, 2L});
+        original.setbWlong(new Long[]{0L, 1L, 2L});
+
+        original.setBfloat(new float[]{0f, 1f, 2f});
+        original.setbWfloat(new Float[]{0f, 1f, 2f});
+
+        original.setBdouble(new double[]{0d, 1d, 2d});
+        original.setbWdouble(new Double[]{0d, 1d, 2d});
+
+        try (final Jsonb jsonb = JsonbBuilder.create()) {
+            final ArrayContainer deserialized = 
jsonb.fromJson(jsonb.toJson(original), ArrayContainer.class);
+            assertEquals(original, deserialized);
+        }
+
+    }
+
+    @Test
+    public void roundTrip() throws Exception {
+        final Wrapper original = new Wrapper();
+        original.uuid = UUID.randomUUID();
+        original.uuid2 = UUID.randomUUID();
+        original.option = Option.YES;
+        original.vatNumber  = new VATNumber(42);
+        original.hello = "hello world";
+        original.color = Color.GREEN;
+
+        try (final Jsonb jsonb = JsonbBuilder.create()) {
+            final Wrapper deserialized = 
jsonb.fromJson(jsonb.toJson(original), Wrapper.class);
+            assertEquals(original, deserialized);
+        }
+    }
+}
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
index b95935e..18b7398 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
@@ -29,7 +29,6 @@ import java.io.Reader;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.Writer;
-import java.lang.reflect.Array;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.math.BigDecimal;
@@ -53,7 +52,7 @@ import javax.json.stream.JsonGeneratorFactory;
 
 import org.apache.johnzon.mapper.internal.JsonPointerTracker;
 import org.apache.johnzon.mapper.reflection.JohnzonCollectionType;
-import org.apache.johnzon.core.util.ArrayUtil;
+import org.apache.johnzon.mapper.util.ArrayUtil;
 
 public class Mapper implements Closeable {
 
@@ -354,7 +353,8 @@ public class Mapper implements Closeable {
     }
 
     private Object mapArray(final Class<?> clazz, final JsonReader reader) {
-        return mapObject(Array.newInstance(clazz, 0).getClass(), reader);
+
+        return mapObject(ArrayUtil.getArrayTypeFor(clazz), reader);
     }
 
 
diff --git 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
index 27de775..04bd2d8 100644
--- 
a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
+++ 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
@@ -21,11 +21,10 @@ package org.apache.johnzon.mapper;
 import static java.util.Collections.emptyList;
 
 import org.apache.johnzon.mapper.internal.JsonPointerTracker;
-import org.apache.johnzon.core.util.ArrayUtil;
+import org.apache.johnzon.mapper.util.ArrayUtil;
 
 import javax.json.JsonValue;
 import javax.json.stream.JsonGenerator;
-import java.lang.reflect.Array;
 import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -591,7 +590,7 @@ public class MappingGeneratorImpl implements 
MappingGenerator {
             if (Collection.class.isInstance(o)) {
                 doWriteIterable(Collection.class.cast(o), ignoredProperties, 
jsonPointer);
             } else if (o.getClass().isArray()) {
-                final int length = Array.getLength(o);
+                final int length = ArrayUtil.getArrayLength(o);
                 if (length > 0 || !config.isSkipEmptyArray()) {
                     writeArray(o.getClass(), null, null, o, ignoredProperties, 
jsonPointer);
                 }
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 43a089c..2d45eb4 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
@@ -658,6 +658,171 @@ public class MappingParserImpl implements MappingParser {
 
     private Object buildArrayWithComponentType(final JsonArray jsonArray, 
final Class<?> componentType, final Adapter itemConverter,
                                                final JsonPointerTracker 
jsonPointer, final Type rootType) {
+
+        if (boolean.class == componentType) {
+            boolean[] array = new boolean[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (boolean) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (byte.class == componentType) {
+            byte[] array = new byte[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (byte) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (char.class == componentType) {
+            char[] array = new char[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (char) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (short.class == componentType) {
+            short[] array = new short[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (short) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (int.class == componentType) {
+            int[] array = new int[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (int) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (long.class == componentType) {
+            long[] array = new long[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (long) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (float.class == componentType) {
+            float[] array = new float[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (float) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (double.class == componentType) {
+            double[] array = new double[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (double) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+
+        // wrapper types
+        if (Boolean.class == componentType) {
+            Boolean[] array = new Boolean[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (Boolean) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (Byte.class == componentType) {
+            Byte[] array = new Byte[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (Byte) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (Character.class == componentType) {
+            Character[] array = new Character[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (Character) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (Short.class == componentType) {
+            Short[] array = new Short[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (Short) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (Integer.class == componentType) {
+            Integer[] array = new Integer[jsonArray.size()];
+            Integer i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (Integer) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (Long.class == componentType) {
+            Long[] array = new Long[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (Long) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (Float.class == componentType) {
+            Float[] array = new Float[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (Float) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+        if (Double.class == componentType) {
+            Double[] array = new Double[jsonArray.size()];
+            int i = 0;
+            for (final JsonValue value : jsonArray) {
+                array[i] = (Double) toObject(null, value, componentType, 
itemConverter,
+                        isDeduplicateObjects ? new 
JsonPointerTracker(jsonPointer, i) : null, rootType);
+                i++;
+            }
+            return array;
+        }
+
+        // for all the rest we have to rely on reflection :(
         final Object array = Array.newInstance(componentType, 
jsonArray.size());
         int i = 0;
         for (final JsonValue value : jsonArray) {
diff --git 
a/johnzon-core/src/main/java/org/apache/johnzon/core/util/ArrayUtil.java 
b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/util/ArrayUtil.java
similarity index 69%
copy from johnzon-core/src/main/java/org/apache/johnzon/core/util/ArrayUtil.java
copy to 
johnzon-mapper/src/main/java/org/apache/johnzon/mapper/util/ArrayUtil.java
index 646c112..0e24bae 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/util/ArrayUtil.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/util/ArrayUtil.java
@@ -14,19 +14,35 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.johnzon.core.util;
+package org.apache.johnzon.mapper.util;
 
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
 import java.util.AbstractList;
 import java.util.List;
 
-/**
- * Various Array utils which do not exist in Java.
+
+/*
+The following types will be handled
+boolean
+byte
+char
+short
+int
+long
+float
+double
+Object
  */
 public final class ArrayUtil {
     private ArrayUtil() {
         // utility class ct
     }
 
+    /**
+     * @return the length of the array given.
+     * @throws IllegalArgumentException if the given object is not an array
+     */
     public static int getArrayLength(Object array) {
         // Note: all types of multidimensional arrays are instanceof Object[]
         if (array instanceof Object[]) {
@@ -160,4 +176,63 @@ public final class ArrayUtil {
     }
 
 
+    /**
+     * @return the array type of a given class
+     */
+    public static Type getArrayTypeFor(Class<?> clazz) {
+        // optimisation for raw types
+        if (boolean.class == clazz) {
+            return boolean[].class;
+        }
+        if (byte.class == clazz) {
+            return byte[].class;
+        }
+        if (char.class == clazz) {
+            return char[].class;
+        }
+        if (short.class == clazz) {
+            return short[].class;
+        }
+        if (int.class == clazz) {
+            return int[].class;
+        }
+        if (long.class == clazz) {
+            return long[].class;
+        }
+        if (float.class == clazz) {
+            return float[].class;
+        }
+        if (double.class == clazz) {
+            return double[].class;
+        }
+
+        // and wrapper types
+        if (Boolean.class == clazz) {
+            return Boolean[].class;
+        }
+        if (Byte.class == clazz) {
+            return Byte[].class;
+        }
+        if (Character.class == clazz) {
+            return Character[].class;
+        }
+        if (Short.class == clazz) {
+            return Short[].class;
+        }
+        if (Integer.class == clazz) {
+            return Integer[].class;
+        }
+        if (Long.class == clazz) {
+            return Long[].class;
+        }
+        if (Float.class == clazz) {
+            return Float[].class;
+        }
+        if (Double.class == clazz) {
+            return Double[].class;
+        }
+
+        // some other class arrays
+        return Array.newInstance(clazz, 0).getClass();
+    }
 }

Reply via email to