You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2016/06/03 15:28:56 UTC

incubator-johnzon git commit: JOHNZON-84 getting rid of default converters for primitives

Repository: incubator-johnzon
Updated Branches:
  refs/heads/master a1246b944 -> 36816c64b


JOHNZON-84 getting rid of default converters for primitives


Project: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/commit/36816c64
Tree: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/tree/36816c64
Diff: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/diff/36816c64

Branch: refs/heads/master
Commit: 36816c64b6f3f327b141b35db666b08ebf1b2348
Parents: a1246b9
Author: Romain manni-Bucau <rm...@gmail.com>
Authored: Fri Jun 3 17:28:22 2016 +0200
Committer: Romain manni-Bucau <rm...@gmail.com>
Committed: Fri Jun 3 17:28:28 2016 +0200

----------------------------------------------------------------------
 .../jaxrs/ConfigurableJohnzonProvider.java      |  4 ++
 .../WildcardConfigurableJohnzonProvider.java    |  4 ++
 .../apache/johnzon/jsonb/JohnzonBuilder.java    |  3 ++
 .../apache/johnzon/mapper/MapperBuilder.java    | 27 ++++++++++++++
 .../johnzon/mapper/MappingGeneratorImpl.java    |  3 ++
 .../johnzon/mapper/MappingParserImpl.java       | 39 +++++++++++++++++++-
 .../org/apache/johnzon/mapper/MapperTest.java   | 16 +++++++-
 7 files changed, 93 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/36816c64/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
index 7bdb597..dd8b79c 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/ConfigurableJohnzonProvider.java
@@ -203,4 +203,8 @@ public class ConfigurableJohnzonProvider<T> implements MessageBodyWriter<T>, Mes
     public void setEnforceQuoteString(final boolean val) {
         builder.setEnforceQuoteString(val);
     }
+
+    public void setPrimitiveConverters(final boolean val) {
+        builder.setPrimitiveConverters(val);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/36816c64/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
index aa44fec..4df4a7c 100644
--- a/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
+++ b/johnzon-jaxrs/src/main/java/org/apache/johnzon/jaxrs/WildcardConfigurableJohnzonProvider.java
@@ -211,4 +211,8 @@ public class WildcardConfigurableJohnzonProvider<T> implements MessageBodyWriter
     public void setEnforceQuoteString(final boolean val) {
         builder.setEnforceQuoteString(val);
     }
+
+    public void setPrimitiveConverters(final boolean val) {
+        builder.setPrimitiveConverters(val);
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/36816c64/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index ea2a937..da23f6a 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -192,6 +192,9 @@ public class JohnzonBuilder implements JsonbBuilder {
         config.getProperty("johnzon.enforceQuoteString")
                 .map(v -> !Boolean.class.isInstance(v) ? Boolean.parseBoolean(v.toString()) : Boolean.class.cast(v))
                 .ifPresent(builder::setEnforceQuoteString);
+        config.getProperty("johnzon.primitiveConverters")
+                .map(v -> !Boolean.class.isInstance(v) ? Boolean.parseBoolean(v.toString()) : Boolean.class.cast(v))
+                .ifPresent(builder::setPrimitiveConverters);
 
         final Map<AdapterKey, Adapter<?, ?>> defaultConverters = createJava8Converters(builder);
 

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/36816c64/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index 9091698..944ed9b 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -80,6 +80,7 @@ public class MapperBuilder {
         DEFAULT_CONVERTERS.put(new AdapterKey(String.class, String.class), new ConverterAdapter<String>(new StringConverter()));
         DEFAULT_CONVERTERS.put(new AdapterKey(BigDecimal.class, String.class), new ConverterAdapter<BigDecimal>(new BigDecimalConverter()));
         DEFAULT_CONVERTERS.put(new AdapterKey(BigInteger.class, String.class), new ConverterAdapter<BigInteger>(new BigIntegerConverter()));
+        /* primitives should be hanlded low level and adapters will wrap them in string which is unlikely
         DEFAULT_CONVERTERS.put(new AdapterKey(Byte.class, String.class), new ConverterAdapter<Byte>(new CachedDelegateConverter<Byte>(new ByteConverter())));
         DEFAULT_CONVERTERS.put(new AdapterKey(Character.class, String.class), new ConverterAdapter<Character>(new CharacterConverter()));
         DEFAULT_CONVERTERS.put(new AdapterKey(Double.class, String.class), new ConverterAdapter<Double>(new DoubleConverter()));
@@ -96,6 +97,7 @@ public class MapperBuilder {
         DEFAULT_CONVERTERS.put(new AdapterKey(long.class, String.class), DEFAULT_CONVERTERS.get(new AdapterKey(Long.class, String.class)));
         DEFAULT_CONVERTERS.put(new AdapterKey(short.class, String.class), DEFAULT_CONVERTERS.get(new AdapterKey(Short.class, String.class)));
         DEFAULT_CONVERTERS.put(new AdapterKey(boolean.class, String.class), DEFAULT_CONVERTERS.get(new AdapterKey(Boolean.class, String.class)));
+        */
         DEFAULT_CONVERTERS.put(new AdapterKey(Locale.class, String.class), new LocaleConverter());
     }
 
@@ -126,6 +128,7 @@ public class MapperBuilder {
     private Map<Class<?>, ObjectConverter.Reader<?>> objectConverterReaders = new HashMap<Class<?>, ObjectConverter.Reader<?>>();
     private Map<Class<?>, ObjectConverter.Writer<?>> objectConverterWriters = new HashMap<Class<?>, ObjectConverter.Writer<?>>();
     private Map<Class<?>, String[]> ignoredForFields = new HashMap<Class<?>, String[]>();
+    private boolean primitiveConverters;
 
     public Mapper build() {
         if (readerFactory == null || generatorFactory == null) {
@@ -186,6 +189,25 @@ public class MapperBuilder {
             }
         }
 
+        if (primitiveConverters) {
+            adapters.put(new AdapterKey(Byte.class, String.class), new ConverterAdapter<Byte>(new CachedDelegateConverter<Byte>(new ByteConverter())));
+            adapters.put(new AdapterKey(Character.class, String.class), new ConverterAdapter<Character>(new CharacterConverter()));
+            adapters.put(new AdapterKey(Double.class, String.class), new ConverterAdapter<Double>(new DoubleConverter()));
+            adapters.put(new AdapterKey(Float.class, String.class), new ConverterAdapter<Float>(new FloatConverter()));
+            adapters.put(new AdapterKey(Integer.class, String.class), new ConverterAdapter<Integer>(new IntegerConverter()));
+            adapters.put(new AdapterKey(Long.class, String.class), new ConverterAdapter<Long>(new LongConverter()));
+            adapters.put(new AdapterKey(Short.class, String.class), new ConverterAdapter<Short>(new ShortConverter()));
+            adapters.put(new AdapterKey(Boolean.class, String.class), new ConverterAdapter<Boolean>(new CachedDelegateConverter<Boolean>(new BooleanConverter())));
+            adapters.put(new AdapterKey(byte.class, String.class), adapters.get(new AdapterKey(Byte.class, String.class)));
+            adapters.put(new AdapterKey(char.class, String.class), adapters.get(new AdapterKey(Character.class, String.class)));
+            adapters.put(new AdapterKey(double.class, String.class), adapters.get(new AdapterKey(Double.class, String.class)));
+            adapters.put(new AdapterKey(float.class, String.class), adapters.get(new AdapterKey(Float.class, String.class)));
+            adapters.put(new AdapterKey(int.class, String.class), adapters.get(new AdapterKey(Integer.class, String.class)));
+            adapters.put(new AdapterKey(long.class, String.class), adapters.get(new AdapterKey(Long.class, String.class)));
+            adapters.put(new AdapterKey(short.class, String.class), adapters.get(new AdapterKey(Short.class, String.class)));
+            adapters.put(new AdapterKey(boolean.class, String.class), adapters.get(new AdapterKey(Boolean.class, String.class)));
+        }
+
         return new Mapper(
                 readerFactory, generatorFactory,
                 new MapperConfig(
@@ -362,4 +384,9 @@ public class MapperBuilder {
         this.enforceQuoteString = val;
         return this;
     }
+
+    public MapperBuilder setPrimitiveConverters(final boolean val) {
+        this.primitiveConverters = val;
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/36816c64/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
----------------------------------------------------------------------
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 3ed0655..a88ab83 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
@@ -339,6 +339,9 @@ public class MappingGeneratorImpl implements MappingGenerator {
                     return;
                 }
             }
+            if (writePrimitives(key, type, value)) {
+                return;
+            }
             generator.writeStartObject(key);
             doWriteObjectBody(value);
             generator.writeEnd();

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/36816c64/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
----------------------------------------------------------------------
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 7a9fcb2..b5a7fab 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
@@ -21,6 +21,7 @@ package org.apache.johnzon.mapper;
 import org.apache.johnzon.core.JsonLongImpl;
 import org.apache.johnzon.core.JsonReaderImpl;
 import org.apache.johnzon.mapper.access.AccessMode;
+import org.apache.johnzon.mapper.converter.CharacterConverter;
 import org.apache.johnzon.mapper.converter.EnumConverter;
 import org.apache.johnzon.mapper.internal.AdapterKey;
 import org.apache.johnzon.mapper.internal.ConverterAdapter;
@@ -35,6 +36,9 @@ import javax.json.JsonStructure;
 import javax.json.JsonValue;
 import javax.xml.bind.DatatypeConverter;
 import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.math.BigDecimal;
@@ -73,9 +77,10 @@ public class MappingParserImpl implements MappingParser {
 
     private static final Adapter<Object, String> FALLBACK_CONVERTER = new ConverterAdapter<Object>(new FallbackConverter());
     private static final JohnzonParameterizedType ANY_LIST = new JohnzonParameterizedType(List.class, Object.class);
-
+    private static final CharacterConverter CHARACTER_CONVERTER = new CharacterConverter(); // this one is particular, share the logic
 
     protected final ConcurrentMap<Adapter<?, ?>, AdapterKey> reverseAdaptersRegistry;
+    protected final ConcurrentMap<Class<?>, Method> valueOfs = new ConcurrentHashMap<Class<?>, Method>();
 
     private final MapperConfig config;
     private final Mappings mappings;
@@ -572,6 +577,38 @@ public class MappingParserImpl implements MappingParser {
             return text;
         }
         final Adapter converter = findAdapter(aClass);
+        Method method = valueOfs.get(aClass);
+        if (method == null && Class.class.isInstance(aClass)) { // handle primitives
+            final Class cast = Class.class.cast(aClass);
+            try {
+                method = cast.getMethod("valueOf", String.class);
+                if (Modifier.isPublic(method.getModifiers()) && Modifier.isStatic(method.getModifiers())) {
+                    valueOfs.putIfAbsent(cast, method);
+                } else {
+                    method = null;
+                }
+            } catch (final NoSuchMethodException e) {
+                // if a real primitive (very unlikely) try the wrapper
+                if (char.class == aClass) {
+                    return CHARACTER_CONVERTER.fromString(text);
+                }
+                try {
+                    return convertTo(Class.class.cast(cast.getField("TYPE").get(null)), text);
+                } catch (final Exception e1) {
+                    // no-op
+                }
+                // no-op
+            }
+        }
+        if (method != null) {
+            try {
+                return method.invoke(null, text);
+            } catch (final IllegalAccessException e) {
+                throw new IllegalStateException(e);
+            } catch (final InvocationTargetException e) {
+                throw new MapperException(e.getCause());
+            }
+        }
         if (converter == null) {
             config.getAdapters().putIfAbsent(new AdapterKey(String.class, aClass), FALLBACK_CONVERTER);
             return FALLBACK_CONVERTER.to(text);

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/36816c64/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
index 7967060..88466e3 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
@@ -191,7 +191,8 @@ public class MapperTest {
                 put("a", "val");
                 put("b", true);
                 put("c", 1);
-            }}, simpleMapper.readObject(new ByteArrayInputStream("{\"a\":\"val\", \"b\": true, \"c\": 1}".getBytes()), Object.class));
+                put("d", true);
+            }}, simpleMapper.readObject(new ByteArrayInputStream("{\"a\":\"val\", \"b\": true, \"c\": 1, \"d\": true}".getBytes()), Object.class));
 
             // write
             assertEquals("true", simpleMapper.writeObjectAsString(true));
@@ -199,12 +200,20 @@ public class MapperTest {
             assertEquals("1", simpleMapper.writeObjectAsString(1));
             assertEquals("\"val\"", enforcedQuotes.writeObjectAsString("val"));
             assertEquals("[\"val1\",\"val2\"]", simpleMapper.writeObjectAsString(asList("val1", "val2")));
-            assertEquals("{\"a\":\"val\",\"b\":true,\"c\":1}", simpleMapper.writeObjectAsString(new TreeMap<String, Object>() {{
+            assertEquals("{\"a\":\"val\",\"b\":true,\"c\":1,\"d\":true}", simpleMapper.writeObjectAsString(new TreeMap<String, Object>() {{
                 put("a", "val");
                 put("b", true);
                 put("c", 1);
+                put("d", true);
             }}));
         }
+        { // in model
+            PrimitiveObject p = new PrimitiveObject();
+            p.bool = true;
+            final Mapper fieldMapper = new MapperBuilder().setAccessModeName("field").build();
+            assertEquals("{\"bool\":true}", fieldMapper.writeObjectAsString(p));
+            assertEquals(Boolean.TRUE, PrimitiveObject.class.cast(fieldMapper.readObject(new StringReader("{\"bool\":true}"), PrimitiveObject.class)).bool);
+        }
     }
 
     private void assertOneDimension(final Map<String, Object> data, final int size) {
@@ -1060,4 +1069,7 @@ public class MapperTest {
         }
     }
 
+    public static class PrimitiveObject {
+        public Object bool;
+    }
 }