http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..9894228
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java
@@ -0,0 +1,368 @@
+/*
+ * 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 org.apache.johnzon.mapper.Mapper;
+import org.apache.johnzon.mapper.MapperException;
+import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbException;
+import java.io.InputStream;
+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.util.Collection;
+import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
+
+// TODO: Optional handling for lists (and arrays)?
+public class JohnzonJsonb implements Jsonb, AutoCloseable {
+    private final Mapper delegate;
+
+    public JohnzonJsonb(final Mapper build) {
+        this.delegate = build;
+    }
+
+    @Override
+    public <T> T fromJson(final String str, final Class<T> type) throws 
JsonbException {
+        try {
+            if (isArray(type)) {
+                return delegate.readTypedArray(new StringReader(str), 
type.getComponentType(), type);
+            } else if (Collection.class.isAssignableFrom(type)) {
+                return (T) delegate.readCollection(new StringReader(str), new 
JohnzonParameterizedType(type, Object.class));
+            }
+            final Type mappingType = unwrapPrimitiveOptional(type);
+            final Object object = delegate.readObject(str, mappingType);
+            if (mappingType != type) {
+                return wrapPrimitiveOptional(object, type);
+            }
+            return (T) object;
+        } catch (final MapperException me) {
+            throw new JsonbException(me.getMessage(), me);
+        }
+    }
+
+    private <T> T wrapPrimitiveOptional(final Object object, final Type type) {
+        if (OptionalDouble.class == type) {
+            if (object == null) {
+                return (T) OptionalDouble.empty();
+            }
+            return (T) 
OptionalDouble.of(Number.class.cast(object).doubleValue());
+        } else if (OptionalInt.class == type) {
+            if (object == null) {
+                return (T) OptionalInt.empty();
+            }
+            return (T) OptionalInt.of(Number.class.cast(object).intValue());
+        } else if (OptionalLong.class == type) {
+            if (object == null) {
+                return (T) OptionalLong.empty();
+            }
+            return (T) OptionalLong.of(Number.class.cast(object).longValue());
+        }
+        // Optional
+        return (T) Optional.ofNullable(object);
+    }
+
+    private Type unwrapPrimitiveOptional(final Type type) {
+        if (OptionalDouble.class == type) {
+            return double.class;
+        } else if (OptionalInt.class == type) {
+            return int.class;
+        } else if (OptionalLong.class == type) {
+            return long.class;
+        } else if (ParameterizedType.class.isInstance(type)) {
+            final ParameterizedType pt = ParameterizedType.class.cast(type);
+            if (Optional.class == pt.getRawType()) {
+                return pt.getActualTypeArguments()[0];
+            }
+        }
+        return type;
+    }
+
+    @Override
+    public <T> T fromJson(final String str, final Type runtimeType) throws 
JsonbException {
+        try {
+            if (isArray(runtimeType)) {
+                final Class cast = Class.class.cast(runtimeType);
+                return (T) delegate.readTypedArray(new StringReader(str), 
cast.getComponentType(), cast);
+            } else if (isCollection(runtimeType)) {
+                return (T) delegate.readCollection(new StringReader(str), 
ParameterizedType.class.cast(runtimeType));
+            }
+            final Type mappingType = unwrapPrimitiveOptional(runtimeType);
+            final Object object = delegate.readObject(str, mappingType);
+            if (mappingType != runtimeType) {
+                return wrapPrimitiveOptional(object, runtimeType);
+            }
+            return (T) object;
+        } catch (final MapperException me) {
+            throw new JsonbException(me.getMessage(), me);
+        }
+    }
+
+    @Override
+    public <T> T fromJson(final Reader reader, final Class<T> type) throws 
JsonbException {
+        try {
+            if (isArray(type)) {
+                return delegate.readTypedArray(reader, 
type.getComponentType(), type);
+            } else if (Collection.class.isAssignableFrom(type)) {
+                return (T) delegate.readCollection(reader, new 
JohnzonParameterizedType(type, Object.class));
+            }
+            final Type mappingType = unwrapPrimitiveOptional(type);
+            final Object object = delegate.readObject(reader, mappingType);
+            if (mappingType != type) {
+                return wrapPrimitiveOptional(object, type);
+            }
+            return (T) object;
+        } catch (final MapperException me) {
+            throw new JsonbException(me.getMessage(), me);
+        }
+    }
+
+    @Override
+    public <T> T fromJson(final Reader reader, final Type runtimeType) throws 
JsonbException {
+        try {
+            if (isArray(runtimeType)) {
+                final Class<T> type = Class.class.cast(runtimeType);
+                return delegate.readTypedArray(reader, 
type.getComponentType(), type);
+            } else if (isCollection(runtimeType)) {
+                return (T) delegate.readCollection(reader, 
ParameterizedType.class.cast(runtimeType));
+            }
+            final Type mappingType = unwrapPrimitiveOptional(runtimeType);
+            final Object object = delegate.readObject(reader, mappingType);
+            if (mappingType != runtimeType) {
+                return wrapPrimitiveOptional(object, runtimeType);
+            }
+            return (T) object;
+        } catch (final MapperException me) {
+            throw new JsonbException(me.getMessage(), me);
+        }
+    }
+
+    @Override
+    public <T> T fromJson(final InputStream stream, final Class<T> type) 
throws JsonbException {
+        try {
+            if (isArray(type)) {
+                return delegate.readTypedArray(stream, 
type.getComponentType(), type);
+            } else if (Collection.class.isAssignableFrom(type)) {
+                return (T) delegate.readCollection(stream, new 
JohnzonParameterizedType(type, Object.class));
+            }
+            final Type mappingType = unwrapPrimitiveOptional(type);
+            final Object object = delegate.readObject(stream, mappingType);
+            if (mappingType != type) {
+                return wrapPrimitiveOptional(object, type);
+            }
+            return (T) object;
+        } catch (final MapperException me) {
+            throw new JsonbException(me.getMessage(), me);
+        }
+    }
+
+    @Override
+    public <T> T fromJson(final InputStream stream, final Type runtimeType) 
throws JsonbException {
+        try {
+            if (isArray(runtimeType)) {
+                final Class<T> type = Class.class.cast(runtimeType);
+                return delegate.readTypedArray(stream, 
type.getComponentType(), type);
+            } else if (isCollection(runtimeType)) {
+                return (T) delegate.readCollection(stream, 
ParameterizedType.class.cast(runtimeType));
+            }
+
+            final Type mappingType = unwrapPrimitiveOptional(runtimeType);
+            final Object object = delegate.readObject(stream, mappingType);
+            if (mappingType != runtimeType) {
+                return wrapPrimitiveOptional(object, runtimeType);
+            }
+            return (T) object;
+        } catch (final MapperException me) {
+            throw new JsonbException(me.getMessage(), me);
+        }
+    }
+
+    @Override
+    public String toJson(final Object inObject) throws JsonbException {
+        try {
+            final Object object = unwrapOptional(inObject);
+            if (object == null) {
+                return "null";
+            }
+            if (isArray(object.getClass())) {
+                return delegate.writeArrayAsString(toArray(object));
+            } else if (Collection.class.isInstance(object)) {
+                return 
delegate.writeArrayAsString(Collection.class.cast(object));
+            }
+            return delegate.writeObjectAsString(object);
+
+        } catch (final MapperException me) {
+            throw new JsonbException(me.getMessage(), me);
+        }
+    }
+
+    private Object[] toArray(final Object object) {
+        final Class<?> componentType = object.getClass().getComponentType();
+        Object[] array;
+        if (int.class == componentType) {
+            final int length = Array.getLength(object);
+            array = new Integer[length];
+            for (int i = 0; i < length; i++) {
+                array[i] = Array.getInt(object, i);
+            }
+        } else if (double.class == componentType) {
+            final int length = Array.getLength(object);
+            array = new Integer[length];
+            for (int i = 0; i < length; i++) {
+                array[i] = Array.getDouble(object, i);
+            }
+        } else if (byte.class == componentType) {
+            final int length = Array.getLength(object);
+            array = new Integer[length];
+            for (int i = 0; i < length; i++) {
+                array[i] = Array.getByte(object, i);
+            }
+        } else if (char.class == componentType) {
+            final int length = Array.getLength(object);
+            array = new Integer[length];
+            for (int i = 0; i < length; i++) {
+                array[i] = Array.getChar(object, i);
+            }
+        } else if (float.class == componentType) {
+            final int length = Array.getLength(object);
+            array = new Integer[length];
+            for (int i = 0; i < length; i++) {
+                array[i] = Array.getFloat(object, i);
+            }
+        } else if (long.class == componentType) {
+            final int length = Array.getLength(object);
+            array = new Integer[length];
+            for (int i = 0; i < length; i++) {
+                array[i] = Array.getLong(object, i);
+            }
+        } else if (short.class == componentType) {
+            final int length = Array.getLength(object);
+            array = new Integer[length];
+            for (int i = 0; i < length; i++) {
+                array[i] = Array.getShort(object, i);
+            }
+        } else {
+            array = (Object[]) object;
+        }
+        return array;
+    }
+
+    @Override
+    public String toJson(final Object inObject, final Type runtimeType) throws 
JsonbException {
+        final Object object = unwrapOptional(inObject);
+        if (object != null && isArray(runtimeType)) {
+            return delegate.writeArrayAsString((Object[]) object);
+        } else if (isCollection(runtimeType)) {
+            return delegate.writeArrayAsString(Collection.class.cast(object));
+        }
+        return delegate.writeObjectAsString(object);
+    }
+
+    @Override
+    public void toJson(final Object inObject, final Writer writer) throws 
JsonbException {
+        final Object object = unwrapOptional(inObject);
+        if (object != null && isArray(object.getClass())) {
+            delegate.writeArray((Object[]) object, writer);
+        } else if (Collection.class.isInstance(object)) {
+            delegate.writeArray(Collection.class.cast(object), writer);
+        } else {
+            delegate.writeObject(object, writer);
+        }
+    }
+
+    @Override
+    public void toJson(final Object inObject, final Type runtimeType, final 
Writer writer) throws JsonbException {
+        final Object object = unwrapOptional(inObject);
+        if (object != null && isArray(runtimeType)) {
+            delegate.writeArray((Object[]) object, writer);
+        } else if (isCollection(runtimeType)) {
+            delegate.writeArray(Collection.class.cast(object), writer);
+        } else {
+            delegate.writeObject(object, writer);
+        }
+    }
+
+    @Override
+    public void toJson(final Object inObject, final OutputStream stream) 
throws JsonbException {
+        final Object object = unwrapOptional(inObject);
+        if (object != null && isArray(object.getClass())) {
+            delegate.writeArray((Object[]) object, stream);
+        } else if (Collection.class.isInstance(object)) {
+            delegate.writeArray(Collection.class.cast(object), stream);
+        } else {
+            delegate.writeObject(object, stream);
+        }
+    }
+
+    @Override
+    public void toJson(final Object inObject, final Type runtimeType, final 
OutputStream stream) throws JsonbException {
+        final Object object = unwrapOptional(inObject);
+        if (object != null && isArray(runtimeType)) {
+            delegate.writeArray((Object[]) object, stream);
+        } else if (isCollection(runtimeType)) {
+            delegate.writeArray(Collection.class.cast(object), stream);
+        } else {
+            delegate.writeObject(object, stream);
+        }
+    }
+
+    private Object unwrapOptional(final Object inObject) {
+        if (Optional.class.isInstance(inObject)) {
+            return Optional.class.cast(inObject).orElse(null);
+        }
+        if (OptionalInt.class.isInstance(inObject)) {
+            final OptionalInt optionalInt = OptionalInt.class.cast(inObject);
+            return optionalInt.isPresent() ? optionalInt.getAsInt() : null;
+        }
+        if (OptionalLong.class.isInstance(inObject)) {
+            final OptionalLong optionalLong = 
OptionalLong.class.cast(inObject);
+            return optionalLong.isPresent() ? optionalLong.getAsLong() : null;
+        }
+        if (OptionalDouble.class.isInstance(inObject)) {
+            final OptionalDouble optionalDouble = 
OptionalDouble.class.cast(inObject);
+            return optionalDouble.isPresent() ? optionalDouble.getAsDouble() : 
null;
+        }
+        return inObject;
+    }
+
+    private boolean isArray(final Type runtimeType) {
+        return Class.class.isInstance(runtimeType) && 
Class.class.cast(runtimeType).isArray();
+    }
+
+    private boolean isCollection(final Type runtimeType) {
+        if (!ParameterizedType.class.isInstance(runtimeType)) {
+            return false;
+        }
+        final Type rawType = 
ParameterizedType.class.cast(runtimeType).getRawType();
+        return Class.class.isInstance(rawType) && 
Collection.class.isAssignableFrom(Class.class.cast(rawType));
+    }
+
+    @Override
+    public void close() {
+        delegate.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
----------------------------------------------------------------------
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 28c7211..4526c72 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
@@ -29,7 +29,10 @@ import 
org.apache.johnzon.jsonb.serializer.JohnzonDeserializationContext;
 import org.apache.johnzon.jsonb.serializer.JohnzonSerializationContext;
 import org.apache.johnzon.jsonb.spi.JohnzonAdapterFactory;
 import org.apache.johnzon.mapper.Adapter;
+import org.apache.johnzon.mapper.Converter;
 import org.apache.johnzon.mapper.JohnzonAny;
+import org.apache.johnzon.mapper.JohnzonConverter;
+import org.apache.johnzon.mapper.MapperConverter;
 import org.apache.johnzon.mapper.ObjectConverter;
 import org.apache.johnzon.mapper.TypeAwareAdapter;
 import org.apache.johnzon.mapper.access.AccessMode;
@@ -100,7 +103,7 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
     private final PropertyNamingStrategy naming;
     private final String order;
     private final PropertyVisibilityStrategy visibility;
-    private final FieldAndMethodAccessMode delegate;
+    private final AccessMode delegate;
     private final boolean caseSensitive;
     private final Map<AdapterKey, Adapter<?, ?>> defaultConverters;
     private final JohnzonAdapterFactory factory;
@@ -122,12 +125,12 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
     public JsonbAccessMode(final PropertyNamingStrategy 
propertyNamingStrategy, final String orderValue,
                            final PropertyVisibilityStrategy 
visibilityStrategy, final boolean caseSensitive,
                            final Map<AdapterKey, Adapter<?, ?>> 
defaultConverters, final JohnzonAdapterFactory factory,
-                           final Supplier<JsonParserFactory> parserFactory) {
+                           final Supplier<JsonParserFactory> parserFactory, 
final AccessMode delegate) {
         this.naming = propertyNamingStrategy;
         this.order = orderValue;
         this.visibility = visibilityStrategy;
         this.caseSensitive = caseSensitive;
-        this.delegate = new FieldAndMethodAccessMode(true, true, false);
+        this.delegate = delegate;
         this.defaultConverters = defaultConverters;
         this.factory = factory;
         this.parserFactory = parserFactory;
@@ -166,11 +169,14 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
         final String[] params;
         final Adapter<?, ?>[] converters;
         final Adapter<?, ?>[] itemConverters;
+        final ObjectConverter.Codec<?>[] objectConverters;
         if (finalConstructor != null || finalFactory != null) {
             types = finalConstructor != null ? 
finalConstructor.getGenericParameterTypes() : 
finalFactory.getGenericParameterTypes();
             params = new String[types.length];
             converters = new Adapter<?, ?>[types.length];
             itemConverters = new Adapter<?, ?>[types.length];
+            objectConverters = new ObjectConverter.Codec<?>[types.length];
+
             int i = 0;
             for (final Parameter parameter : (finalConstructor == null ? 
finalFactory : finalConstructor).getParameters()) {
                 final JsonbProperty property = getAnnotation(parameter, 
JsonbProperty.class);
@@ -179,20 +185,25 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
                 final JsonbTypeAdapter adapter = getAnnotation(parameter, 
JsonbTypeAdapter.class);
                 final JsonbDateFormat dateFormat = getAnnotation(parameter, 
JsonbDateFormat.class);
                 final JsonbNumberFormat numberFormat = 
getAnnotation(parameter, JsonbNumberFormat.class);
-                if (adapter == null && dateFormat == null && numberFormat == 
null) {
+                final JohnzonConverter johnzonConverter = 
getAnnotation(parameter, JohnzonConverter.class);
+                if (adapter == null && dateFormat == null && numberFormat == 
null && johnzonConverter == null) {
                     converters[i] = defaultConverters.get(parameter.getType());
                     itemConverters[i] = null;
                 } else {
-                    validateAnnotations(parameter, adapter, dateFormat, 
numberFormat);
+                    validateAnnotations(parameter, adapter, dateFormat, 
numberFormat, johnzonConverter);
 
                     try {
-                        final Adapter converter = 
toConverter(parameter.getType(), adapter, dateFormat, numberFormat);
-                        if (matches(parameter.getParameterizedType(), 
converter)) {
-                            converters[i] = converter;
-                            itemConverters[i] = null;
-                        } else {
-                            converters[i] = null;
-                            itemConverters[i] = converter;
+                        if (adapter != null) {
+                            final Adapter converter = 
toConverter(parameter.getType(), adapter, dateFormat, numberFormat);
+                            if (matches(parameter.getParameterizedType(), 
converter)) {
+                                converters[i] = converter;
+                                itemConverters[i] = null;
+                            } else {
+                                converters[i] = null;
+                                itemConverters[i] = converter;
+                            }
+                        } else if (johnzonConverter != null) {
+                            objectConverters[i] = (ObjectConverter.Codec<?>) 
johnzonConverter.value().newInstance();
                         }
                     } catch (final InstantiationException | 
IllegalAccessException e) {
                         throw new IllegalArgumentException(e);
@@ -206,6 +217,7 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
             params = null;
             converters = null;
             itemConverters = null;
+            objectConverters = null;
         }
 
         return constructor == null && factory == null ? 
delegate.findFactory(clazz) : (
@@ -241,6 +253,11 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
                             public Adapter<?, ?>[] getParameterItemConverter() 
{
                                 return itemConverters;
                             }
+
+                            @Override
+                            public ObjectConverter.Codec<?>[] 
getObjectConverter() {
+                                return objectConverters;
+                            }
                         } :
                         new Factory() {
                             @Override
@@ -277,17 +294,24 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
                             public Adapter<?, ?>[] getParameterItemConverter() 
{
                                 return itemConverters;
                             }
+
+                            @Override
+                            public ObjectConverter.Codec<?>[] 
getObjectConverter() {
+                                return objectConverters;
+                            }
                         });
     }
 
     private void validateAnnotations(final Object parameter,
                                      final JsonbTypeAdapter adapter, final 
JsonbDateFormat dateFormat,
-                                     final JsonbNumberFormat numberFormat) {
+                                     final JsonbNumberFormat numberFormat,
+                                     final JohnzonConverter johnzonConverter) {
         int notNull = adapter != null ? 1 : 0;
         notNull += dateFormat != null ? 1 : 0;
         notNull += numberFormat != null ? 1 : 0;
+        notNull += johnzonConverter != null ? 1 : 0;
         if (notNull > 1) {
-            throw new IllegalArgumentException("Conflicting @JsonbXXX on " + 
parameter);
+            throw new IllegalArgumentException("Conflicting 
@JsonbXXX/@JohnzonConverter on " + parameter);
         }
     }
 
@@ -612,10 +636,28 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
         final JsonbPropertyOrder orderAnnotation = Meta.getAnnotation(clazz, 
JsonbPropertyOrder.class);
         if (orderAnnotation != null) {
             final List<String> indexed = new 
ArrayList<>(asList(orderAnnotation.value()));
+            if (naming != null) { // JsonbPropertyOrder applies on java names
+                for (int i = 0; i < indexed.size(); i++) {
+                    indexed.set(i, naming.translateName(indexed.get(i)));
+                }
+            }
             keyComparator = (o1, o2) -> {
                 final int i1 = indexed.indexOf(o1);
                 final int i2 = indexed.indexOf(o2);
                 if (i1 < 0) {
+                    if (i2 < 0) {
+                        if (order != null) {
+                            switch (order) {
+                                case PropertyOrderStrategy.LEXICOGRAPHICAL:
+                                    return o1.compareTo(o2);
+                                case PropertyOrderStrategy.REVERSE:
+                                    return o2.compareTo(o1);
+                                case PropertyOrderStrategy.ANY:
+                                default:
+                                    return 1;
+                            }
+                        }
+                    }
                     return 1;
                 }
                 return i1 - i2;
@@ -629,7 +671,7 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
                     keyComparator = String::compareTo;
                     break;
                 case PropertyOrderStrategy.REVERSE:
-                    keyComparator = (o1, o2) -> o2.compareTo(o1);
+                    keyComparator = Comparator.reverseOrder();
                     break;
                 default:
                     keyComparator = null;
@@ -643,6 +685,9 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
     @Override
     public void close() throws IOException {
         toRelease.forEach(JohnzonAdapterFactory.Instance::release);
+        if (Closeable.class.isInstance(delegate)) {
+            Closeable.class.cast(delegate).close();
+        }
         toRelease.clear();
     }
 
@@ -664,10 +709,11 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
             final JsonbTypeAdapter adapter = 
annotationHolder.getAnnotation(JsonbTypeAdapter.class);
             final JsonbDateFormat dateFormat = 
annotationHolder.getAnnotation(JsonbDateFormat.class);
             final JsonbNumberFormat numberFormat = 
annotationHolder.getAnnotation(JsonbNumberFormat.class);
-            validateAnnotations(annotationHolder, adapter, dateFormat, 
numberFormat);
+            final JohnzonConverter johnzonConverter = 
annotationHolder.getAnnotation(JohnzonConverter.class);
+            validateAnnotations(annotationHolder, adapter, dateFormat, 
numberFormat, johnzonConverter);
 
             try {
-                converter = adapter == null && dateFormat == null && 
numberFormat == null ?
+                converter = adapter == null && dateFormat == null && 
numberFormat == null && johnzonConverter == null ?
                         defaultConverters.get(new 
AdapterKey(annotationHolder.getType(), String.class)) :
                         toConverter(annotationHolder.getType(), adapter, 
dateFormat, numberFormat);
             } catch (final InstantiationException | IllegalAccessException e) {
@@ -684,8 +730,17 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
                 toRelease.add(instance);
                 reader = (jsonObject, targetType, parser) ->
                         
instance.getValue().deserialize(parserFactory.get().createParser(jsonObject), 
new JohnzonDeserializationContext(parser), targetType);
-            } else {
-                reader = null;
+            } else if (johnzonConverter != null) {
+                try {
+                    MapperConverter mapperConverter = 
johnzonConverter.value().newInstance();
+                    if (mapperConverter instanceof Converter) {
+                        converter = new ConverterAdapter<>((Converter) 
mapperConverter);
+                    } else if (mapperConverter instanceof 
ObjectConverter.Reader) {
+                        reader = (ObjectConverter.Reader) mapperConverter;
+                    }
+                } catch (final InstantiationException | IllegalAccessException 
e) {
+                    throw new IllegalArgumentException(e);
+                }
             }
         }
     }
@@ -699,10 +754,11 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
             final JsonbTypeAdapter adapter = 
initialReader.getAnnotation(JsonbTypeAdapter.class);
             final JsonbDateFormat dateFormat = 
initialReader.getAnnotation(JsonbDateFormat.class);
             final JsonbNumberFormat numberFormat = 
initialReader.getAnnotation(JsonbNumberFormat.class);
-            validateAnnotations(initialReader, adapter, dateFormat, 
numberFormat);
+            final JohnzonConverter johnzonConverter = 
initialReader.getAnnotation(JohnzonConverter.class);
+            validateAnnotations(initialReader, adapter, dateFormat, 
numberFormat, johnzonConverter);
 
             try {
-                converter = adapter == null && dateFormat == null && 
numberFormat == null ?
+                converter = adapter == null && dateFormat == null && 
numberFormat == null && johnzonConverter == null ?
                         defaultConverters.get(new 
AdapterKey(initialReader.getType(), String.class)) :
                         toConverter(initialReader.getType(), adapter, 
dateFormat, numberFormat);
             } catch (final InstantiationException | IllegalAccessException e) {
@@ -719,8 +775,17 @@ public class JsonbAccessMode implements AccessMode, 
Closeable {
                 toRelease.add(instance);
                 writer = (instance1, jsonbGenerator) ->
                         instance.getValue().serialize(instance1, 
jsonbGenerator.getJsonGenerator(), new 
JohnzonSerializationContext(jsonbGenerator));
-            } else {
-                writer = null;
+            } else if (johnzonConverter != null) {
+                try {
+                    MapperConverter mapperConverter = 
johnzonConverter.value().newInstance();
+                    if (mapperConverter instanceof Converter) {
+                        converter = new ConverterAdapter<>((Converter) 
mapperConverter) ;
+                    } else if (mapperConverter instanceof 
ObjectConverter.Writer) {
+                        writer = (ObjectConverter.Writer) mapperConverter;
+                    }
+                } catch (final InstantiationException | IllegalAccessException 
e) {
+                    throw new IllegalArgumentException(e);
+                }
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java
index 9f92c9a..e119fd8 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java
@@ -18,7 +18,7 @@
  */
 package org.apache.johnzon.jsonb.cdi;
 
-import org.apache.johnzon.jsonb.JohnsonJsonb;
+import org.apache.johnzon.jsonb.JohnzonJsonb;
 
 // helper class to lazy trigger CDI deps
 public final class CDIs {
@@ -28,12 +28,12 @@ public final class CDIs {
         this.tracker = Lazy.load(beanManager);
     }
 
-    public void track(final JohnsonJsonb johnsonJsonb) {
-        tracker.track(johnsonJsonb);
+    public void track(final JohnzonJsonb johnzonJsonb) {
+        tracker.track(johnzonJsonb);
     }
 
-    public void untrack(final JohnsonJsonb johnsonJsonb) {
-        tracker.untrack(johnsonJsonb);
+    public void untrack(final JohnzonJsonb johnzonJsonb) {
+        tracker.untrack(johnzonJsonb);
     }
 
     public boolean isCanWrite() {

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java
 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java
index 17dae3c..ee42c9a 100644
--- 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java
+++ 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java
@@ -18,7 +18,7 @@
  */
 package org.apache.johnzon.jsonb.cdi;
 
-import org.apache.johnzon.jsonb.JohnsonJsonb;
+import org.apache.johnzon.jsonb.JohnzonJsonb;
 
 import javax.enterprise.event.Observes;
 import javax.enterprise.inject.spi.BeforeBeanDiscovery;
@@ -29,7 +29,7 @@ import java.util.Collection;
 import java.util.concurrent.locks.ReentrantLock;
 
 public class JohnzonCdiExtension implements Extension {
-    private final Collection<JohnsonJsonb> jsonbs = new ArrayList<>();
+    private final Collection<JohnzonJsonb> jsonbs = new ArrayList<>();
     private final ReentrantLock lock = new ReentrantLock();
     private volatile boolean canWrite = false;
 
@@ -37,7 +37,7 @@ public class JohnzonCdiExtension implements Extension {
         return canWrite;
     }
 
-    public void track(final JohnsonJsonb jsonb) {
+    public void track(final JohnzonJsonb jsonb) {
         if (!canWrite) {
             throw new IllegalStateException("CDI context already shutdown");
         }
@@ -49,7 +49,7 @@ public class JohnzonCdiExtension implements Extension {
         }
     }
 
-    public void untrack(final JohnsonJsonb jsonb) {
+    public void untrack(final JohnzonJsonb jsonb) {
         synchronized (this) {
             lock.lock();
             try {

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java
 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java
index c9992b2..7fc505f 100644
--- 
a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java
+++ 
b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java
@@ -24,36 +24,36 @@ import javax.json.bind.JsonbException;
 import javax.json.bind.adapter.JsonbAdapter;
 import java.lang.reflect.Type;
 
-public class JohnzonJsonbAdapter<A, B> implements TypeAwareAdapter<A, B> {
-    private final JsonbAdapter<A, B> delegate;
+public class JohnzonJsonbAdapter<JsonType, OriginalType> implements 
TypeAwareAdapter<OriginalType, JsonType> {
+    private final JsonbAdapter<OriginalType, JsonType> delegate;
     private final Type from;
     private final Type to;
 
-    public JohnzonJsonbAdapter(final JsonbAdapter<A, B> delegate, final Type 
from, final Type to) {
+    public JohnzonJsonbAdapter(final JsonbAdapter<OriginalType, JsonType> 
delegate, final Type from, final Type to) {
         this.delegate = delegate;
         this.from = from;
         this.to = to;
     }
 
     @Override
-    public A to(final B obj) {
+    public OriginalType to(final JsonType obj) {
         if (obj == null) {
             return null;
         }
         try {
-            return delegate.adaptToJson(obj);
+            return delegate.adaptFromJson(obj);
         } catch (final Exception e) {
             throw new JsonbException(e.getMessage(), e);
         }
     }
 
     @Override
-    public B from(final A obj) {
+    public JsonType from(final OriginalType obj) {
         if (obj == null) {
             return null;
         }
         try {
-            return delegate.adaptFromJson(obj);
+            return delegate.adaptToJson(obj);
         } catch (final Exception e) {
             throw new JsonbException(e.getMessage(), e);
         }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java
index 05b80da..775442e 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java
@@ -132,12 +132,12 @@ public class AdapterTest {
 
     public static class PolyBarAdapter implements JsonbAdapter<Bar, 
TypeInstance> {
         @Override
-        public Bar adaptToJson(final TypeInstance obj) throws Exception {
+        public Bar adaptFromJson(final TypeInstance obj) throws Exception {
             return obj.value;
         }
 
         @Override
-        public TypeInstance adaptFromJson(final Bar obj) throws Exception {
+        public TypeInstance adaptToJson(final Bar obj) throws Exception {
             final TypeInstance typeInstance = new TypeInstance();
             typeInstance.type = obj.getClass().getName();
             typeInstance.value = obj;
@@ -151,29 +151,29 @@ public class AdapterTest {
 
     public static class DummyAdapter implements JsonbAdapter<Dummy, String> {
         @Override
-        public Dummy adaptToJson(final String obj) throws Exception {
+        public Dummy adaptFromJson(final String obj) throws Exception {
             final Dummy bar = new Dummy();
             bar.value = Long.parseLong(obj);
             return bar;
         }
 
         @Override
-        public String adaptFromJson(final Dummy obj) throws Exception {
+        public String adaptToJson(final Dummy obj) throws Exception {
             return Long.toString(obj.value);
         }
     }
 
     public static class BarAdapter implements JsonbAdapter<Bar, String> {
         @Override
-        public Bar adaptToJson(final String obj) throws Exception {
-            final Bar bar = new Bar();
-            bar.value = Integer.parseInt(obj);
-            return bar;
+        public String adaptToJson(final Bar obj) throws Exception {
+            return Integer.toString(obj.value);
         }
 
         @Override
-        public String adaptFromJson(final Bar obj) throws Exception {
-            return Integer.toString(obj.value);
+        public Bar adaptFromJson(final String obj) throws Exception {
+            final Bar bar = new Bar();
+            bar.value = Integer.parseInt(obj);
+            return bar;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AnnotationOrderTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AnnotationOrderTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AnnotationOrderTest.java
new file mode 100644
index 0000000..3c75869
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AnnotationOrderTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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 org.junit.Test;
+
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbConfig;
+import javax.json.bind.annotation.JsonbPropertyOrder;
+import javax.json.bind.config.PropertyNamingStrategy;
+
+import static org.junit.Assert.assertEquals;
+
+public class AnnotationOrderTest {
+    /**
+     * Test that @JsonbPropertyOrder takes java names and pushes at the end 
not mentionned properties.
+     */
+    @Test
+    public void run() {
+        final Person p = new Person();
+        p.setPersonAge(12);
+        p.setPersonName("David");
+        p.setPersonGender("Male");
+        assertEquals(
+                
"{\"person_gender\":\"Male\",\"person_name\":\"David\",\"person_age\":12}",
+                JsonbBuilder.create(new 
JsonbConfig().withPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES))
+                        .toJson(p));
+    }
+
+    @JsonbPropertyOrder({"personGender", "personName"})
+    public class Person {
+        private String personName;
+        private int personAge;
+        private String personGender;
+
+        public String getPersonName() {
+            return personName;
+        }
+
+        public void setPersonName(String name) {
+            this.personName = name;
+        }
+
+        public int getPersonAge() {
+            return personAge;
+        }
+
+        public void setPersonAge(int age) {
+            this.personAge = age;
+        }
+
+        public String getPersonGender() {
+            return personGender;
+        }
+
+        public void setPersonGender(String personGender) {
+            this.personGender = personGender;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java
index 322325f..79685bb 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java
@@ -90,12 +90,12 @@ public class CdiAdapterTest {
         private Service service;
 
         @Override
-        public Model adaptToJson(final String obj) throws Exception {
+        public Model adaptFromJson(final String obj) throws Exception {
             throw new UnsupportedOperationException();
         }
 
         @Override
-        public String adaptFromJson(final Model obj) throws Exception {
+        public String adaptToJson(final Model obj) throws Exception {
             assertTrue(OwbNormalScopeProxy.class.isInstance(service)); // 
additional test
             return service.toString(obj);
         }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java
index 63a66c6..940404a 100644
--- 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java
@@ -93,7 +93,7 @@ public class ClassConverterTest {
         }
     }
 
-    public static class MyAdapter implements JsonbAdapter<Whole, Switch> {
+    public static class MyAdapter implements JsonbAdapter<Switch, Whole> {
         @Override
         public Whole adaptToJson(final Switch obj) throws Exception {
             final Whole whole = new Whole();

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CustomParameterizedTypeTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CustomParameterizedTypeTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CustomParameterizedTypeTest.java
new file mode 100644
index 0000000..7b5e2cc
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CustomParameterizedTypeTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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 org.junit.Test;
+
+import javax.json.bind.spi.JsonbProvider;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Map;
+import java.util.Objects;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class CustomParameterizedTypeTest {
+    @Test
+    public void run() {
+        final String value = "{\"val1\":{\"name\":\"the name\",\"age\":1234}}";
+        final Object map = 
JsonbProvider.provider().create().build().fromJson(value, new 
ParameterizedType() {
+            @Override
+            public Type[] getActualTypeArguments() {
+                return new Type[]{String.class, Value.class};
+            }
+
+            @Override
+            public Type getRawType() {
+                return Map.class;
+            }
+
+            @Override
+            public Type getOwnerType() {
+                return null;
+            }
+        });
+        assertThat(map, instanceOf(Map.class));
+        final Map<String, Value> asMap = Map.class.cast(map);
+        assertTrue(asMap.containsKey("val1"));
+        assertEquals(1, asMap.size());
+        assertEquals(1234, asMap.get("val1").age);
+        assertEquals("the name", asMap.get("val1").name);
+    }
+
+    public static class Value {
+        private String name;
+        private int age;
+
+        public String getName() {
+            return this.name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public int getAge() {
+            return this.age;
+        }
+
+        public void setAge(int age) {
+            this.age = age;
+        }
+
+        @Override
+        public int hashCode() {
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj == null || obj.getClass() != getClass()) {
+                return false;
+            }
+            Value other = (Value) obj;
+            return Objects.equals(this.name, other.name)
+                    && Objects.equals(this.age, other.age);
+        }
+
+        @Override
+        public String toString() {
+            return this.name + " " + this.age;
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java
----------------------------------------------------------------------
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 5c99371..d638d5a 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
@@ -340,11 +340,11 @@ public class DefaultMappingTest {
         //Map
         Map<String, Object> map = (Map<String, Object>) 
JSONB.fromJson("{\"name\":\"unknown object\"}", Object.class);
 
-        //mapping for number  -> Integer, Long, BigDecimal
-        Map<String, Object> mapWithBigDecimal = (Map<String, Object>) 
JSONB.fromJson("{\"intValue\":5,\"longValue\":17179869184,\"otherValue\":1.2}", 
Object.class);
+        //mapping for number  -> Integer, Long, Double
+        Map<String, Object> mapWithBigDecimal = (Map<String, Object>) 
JSONB.fromJson("{\"intValue\":5,\"longValue\":17179869184,\"doubleValue\":1.2}",
 Object.class);
         assertTrue(mapWithBigDecimal.get("intValue") instanceof Integer);
         assertTrue(mapWithBigDecimal.get("longValue") instanceof Long);
-        assertTrue(mapWithBigDecimal.get("otherValue") instanceof BigDecimal);
+        assertTrue(mapWithBigDecimal.get("doubleValue") instanceof Double);
 
         //Collection
         /* why collection and not array or sthg else?

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DynamicBufferResizingTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DynamicBufferResizingTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DynamicBufferResizingTest.java
new file mode 100644
index 0000000..6345a9b
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DynamicBufferResizingTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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 javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbConfig;
+import javax.json.bind.annotation.JsonbCreator;
+import javax.json.bind.annotation.JsonbProperty;
+import javax.json.bind.annotation.JsonbPropertyOrder;
+import javax.json.bind.config.BinaryDataStrategy;
+
+import org.junit.Test;
+
+public class DynamicBufferResizingTest {
+    @Test
+    public void main() {
+        final JsonbConfig config = new JsonbConfig()
+                .withFormatting(Boolean.TRUE)
+                .withBinaryDataStrategy(BinaryDataStrategy.BASE_64);
+        Jsonb jsonb = JsonbBuilder.create(config);
+
+        final Request request = new Request("Screenshot.png", "image/png", new 
byte[558140]);
+        String json = jsonb.toJson(request);
+
+        // the first call works
+        for (int i = 0; i < 10; i++) { // originally the second call was 
failling
+            final Request fromJson = jsonb.fromJson(json, Request.class);
+            assertEquals("Screenshot.png", fromJson.name);
+            assertEquals("image/png", fromJson.mimeType);
+            assertEquals(558140, fromJson.body.length);
+        }
+    }
+
+    @JsonbPropertyOrder(value = {"name", "mimeType"})
+    public static class Request {
+        private String name;
+        private String mimeType;
+        private byte[] body;
+
+        @JsonbCreator
+        public Request(
+                final @JsonbProperty("name") String name,
+                final @JsonbProperty("mimeType") String mimeType,
+                final @JsonbProperty("body") byte[] body) {
+            this.name = name;
+            this.mimeType = mimeType;
+            this.body = body;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public String getMimeType() {
+            return mimeType;
+        }
+
+        public void setMimeType(String mimeType) {
+            this.mimeType = mimeType;
+        }
+
+        public byte[] getBody() {
+            return body;
+        }
+
+        public void setBody(byte[] body) {
+            this.body = body;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/FailOnUnknownPropertiesTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/FailOnUnknownPropertiesTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/FailOnUnknownPropertiesTest.java
new file mode 100644
index 0000000..90f3bf1
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/FailOnUnknownPropertiesTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.junit.Test;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbConfig;
+import javax.json.bind.JsonbException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class FailOnUnknownPropertiesTest {
+    @Test
+    public void failOnUnknownProperties() {
+        final Jsonb jsonb = JsonbBuilder.create(new 
JsonbConfig().setProperty("johnzon.fail-on-unknown-properties", true));
+
+        // valid
+        assertEquals("ok", jsonb.fromJson("{\"known\":\"ok\"}", 
Model.class).known);
+
+        try { // invalid
+            assertEquals("ok", 
jsonb.fromJson("{\"known\":\"ok\",\"unknown\":\"whatever\"}", 
Model.class).known);
+            fail();
+        } catch (final JsonbException jsone) {
+            assertEquals("(fail on unknown properties): [unknown]", 
jsone.getMessage());
+        }
+        try { // invalid but a missing key from the model
+            assertEquals("ok", jsonb.fromJson("{\"unknown\":\"whatever\"}", 
Model.class).known);
+            fail();
+        } catch (final JsonbException jsone) {
+            assertEquals("(fail on unknown properties): [unknown]", 
jsone.getMessage());
+        }
+    }
+
+    public static class Model {
+        public String known;
+    }
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java
new file mode 100644
index 0000000..f9de06a
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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 java.lang.reflect.Type;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import javax.json.JsonObject;
+import javax.json.bind.Jsonb;
+import javax.json.bind.spi.JsonbProvider;
+
+import org.apache.johnzon.mapper.Converter;
+import org.apache.johnzon.mapper.JohnzonConverter;
+import org.apache.johnzon.mapper.MappingGenerator;
+import org.apache.johnzon.mapper.MappingParser;
+import org.apache.johnzon.mapper.ObjectConverter;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Test that a Johnzon Converter works even in JsonB mode
+ */
+public class JohnzonConverterInJsonbTest {
+
+    @Test
+    public void testJohnzonConverter() {
+        TestDTO dto = new TestDTO();
+        dto.setInstant(Instant.now());
+
+        Jsonb jsonb = JsonbProvider.provider().create().build();
+        String json = jsonb.toJson(dto);
+        assertNotNull(json);
+
+        TestDTO deserialized = jsonb.fromJson(json, TestDTO.class);
+        assertEquals(dto.instant, deserialized.instant);
+    }
+
+    @Test
+    public void testObjectConverter() {
+        TestDTOWithOC dto = new TestDTOWithOC();
+        dto.dto = new TestDTO();
+        dto.dto.instant = Instant.now();
+
+        Jsonb jsonb = JsonbProvider.provider().create().build();
+        String json = jsonb.toJson(dto);
+        assertNotNull(json);
+
+        TestDTOWithOC deserialized = jsonb.fromJson(json, TestDTOWithOC.class);
+        assertEquals(deserialized.dto.instant, dto.dto.instant);
+    }
+
+    public static class TestDTOWithOC {
+        @JohnzonConverter(TestDTOConverter.class)
+        private TestDTO dto;
+
+        public TestDTO getDto() {
+            return dto;
+        }
+
+        public void setDto(TestDTO dto) {
+            this.dto = dto;
+        }
+    }
+
+    public static class TestDTOConverter implements 
ObjectConverter.Codec<TestDTO> {
+
+        private static final String TIMESTAMP_JSON_KEY = "timestamp";
+
+        @Override
+        public void writeJson(TestDTO instance, MappingGenerator 
jsonbGenerator) {
+            jsonbGenerator.getJsonGenerator().write(TIMESTAMP_JSON_KEY, 
instance.instant.atZone(ZoneId.of("UTC")).toString());
+        }
+
+        @Override
+        public TestDTO fromJson(JsonObject jsonObject, Type targetType, 
MappingParser parser) {
+            TestDTO dto = new TestDTO();
+            dto.instant = 
ZonedDateTime.parse(jsonObject.getString(TIMESTAMP_JSON_KEY)).toInstant();
+            return dto;
+        }
+    }
+
+    public static class TestDTO {
+        @JohnzonConverter(TestInstantConverter.class)
+        private Instant instant;
+
+        public Instant getInstant() {
+            return instant;
+        }
+
+        public void setInstant(Instant instant) {
+            this.instant = instant;
+        }
+    }
+
+
+    public static class TestInstantConverter implements Converter<Instant> {
+        public static final DateTimeFormatter FORMAT = 
DateTimeFormatter.ofPattern(
+                "yyyy-MM-dd HH:mm:ss.SSS");
+
+        @Override
+        public String toString(Instant date) {
+            return FORMAT.withZone(ZoneId.of("UTC")).format(date);
+        }
+
+        @Override
+        public Instant fromString(String dateStr) {
+            return LocalDateTime.parse(dateStr, FORMAT)
+                    .atZone(ZoneId.of("UTC"))
+                    .toInstant();
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonIgnoreNestedTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonIgnoreNestedTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonIgnoreNestedTest.java
new file mode 100644
index 0000000..2bf3815
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonIgnoreNestedTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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 org.apache.johnzon.mapper.JohnzonIgnoreNested;
+import org.junit.Test;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.spi.JsonbProvider;
+import java.util.Collection;
+
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertEquals;
+
+public class JohnzonIgnoreNestedTest {
+    @Test
+    public void ignoreNested() {
+        final To to = new To();
+        to.name = "to";
+
+        final Person from = new Person();
+        from.name = "myname";
+        from.street = "blastreet 1";
+        from.description = "gets ignored";
+
+        to.person = from;
+        to.persons = singletonList(from);
+
+
+        final Jsonb jsonb =  JsonbProvider.provider().create().build();
+        
assertEquals("{\"name\":\"to\",\"person\":{\"name\":\"myname\"},\"persons\":[{\"name\":\"myname\"}]}",
 jsonb.toJson(to));
+    }
+
+    public static class To {
+        public String name;
+
+        @JohnzonIgnoreNested(properties = {"street", "description"})
+        public Person person;
+
+        @JohnzonIgnoreNested(properties = {"street", "description"})
+        public Collection<Person> persons;
+    }
+
+    public static class Person {
+        public String name;
+        public String street;
+        public String description;
+    }
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java
index 4b19cff..bd63127 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java
@@ -20,16 +20,40 @@ package org.apache.johnzon.jsonb;
 
 import org.junit.Test;
 
+import javax.json.bind.JsonbConfig;
+import javax.json.bind.JsonbException;
 import javax.json.bind.annotation.JsonbDateFormat;
 import javax.json.bind.annotation.JsonbProperty;
+import javax.json.bind.config.BinaryDataStrategy;
 import javax.json.bind.spi.JsonbProvider;
+
+import java.io.ByteArrayInputStream;
 import java.io.StringReader;
+import java.nio.charset.StandardCharsets;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.util.Base64;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 public class JsonbReadTest {
+
+    @Test
+    public void boolFromString() {
+        assertTrue(JsonbProvider.provider().create().build().fromJson("true", 
Boolean.class));
+    }
+
+    @Test
+    public void boolFromReader() {
+        assertTrue(JsonbProvider.provider().create().build().fromJson(new 
StringReader("true"), Boolean.class));
+    }
+
+    @Test
+    public void boolFromStream() {
+        assertTrue(JsonbProvider.provider().create().build().fromJson(new 
ByteArrayInputStream("true".getBytes()), Boolean.class));
+    }
+
     @Test
     public void simple() {
         assertEquals("test", 
JsonbProvider.provider().create().build().fromJson(new 
StringReader("{\"value\":\"test\"}"), Simple.class).value);
@@ -48,6 +72,51 @@ public class JsonbReadTest {
             JsonbProvider.provider().create().build().fromJson(new 
StringReader("{\"date\":\"" + date + "\"}"), 
DateFormatting.class).date.getYear());
     }
 
+    @Test
+    public void propertyMappingNewLine() {
+        String json = "{\n" +
+                "  \"simple\":\"test\"\n" +
+                "}\n";
+
+        assertEquals("test", 
JsonbProvider.provider().create().build().fromJson(new StringReader(json), 
SimpleProperty.class).value);
+    }
+
+    @Test
+    public void propertyMappingNewLineCr() {
+        String json = "{\r\n" +
+                "  \"simple\":\"test\"\r\n" +
+                "}\r\n";
+
+        assertEquals("test", 
JsonbProvider.provider().create().build().fromJson(new StringReader(json), 
SimpleProperty.class).value);
+    }
+
+    @Test
+    public void propertyMappingNewLineTabs() {
+        String json = "{\n" +
+                "\t\"simple\":\"test\"\n" +
+                "}\n";
+
+        assertEquals("test", 
JsonbProvider.provider().create().build().fromJson(new StringReader(json), 
SimpleProperty.class).value);
+    }
+
+    @Test
+    public void testValidBase64() {
+        String json = "{\"blob\":\"" + 
Base64.getEncoder().encodeToString("test".getBytes(StandardCharsets.UTF_8)) + 
"\"}";
+        JsonbConfig cfg = new JsonbConfig()
+                .withBinaryDataStrategy(BinaryDataStrategy.BASE_64);
+        SimpleBinaryDto simpleBinaryDto = 
JsonbProvider.provider().create().withConfig(cfg).build().fromJson(new 
StringReader(json), SimpleBinaryDto.class);
+        assertEquals("test", new String(simpleBinaryDto.getBlob(), 
StandardCharsets.UTF_8));
+    }
+
+    @Test(expected = JsonbException.class)
+    public void testInvalidBase64() {
+        String jsonWithIllegalBase64 = "{\"blob\":\"dGVXz@dA==\"}";
+        JsonbConfig cfg = new JsonbConfig()
+                .withBinaryDataStrategy(BinaryDataStrategy.BASE_64);
+        SimpleBinaryDto simpleBinaryDto = 
JsonbProvider.provider().create().withConfig(cfg).build().fromJson(new 
StringReader(jsonWithIllegalBase64), SimpleBinaryDto.class);
+    }
+
+
     public static class Simple {
         private String value;
 
@@ -99,4 +168,16 @@ public class JsonbReadTest {
             this.date = value;
         }
     }
+
+    public static class SimpleBinaryDto {
+        private byte[] blob;
+
+        public byte[] getBlob() {
+            return blob;
+        }
+
+        public void setBlob(byte[] blob) {
+            this.blob = blob;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java
index 0f792df..ad5b6d2 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java
@@ -36,11 +36,13 @@ import java.time.Period;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.util.Calendar;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.GregorianCalendar;
+import java.util.Locale;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.OptionalDouble;
@@ -49,6 +51,7 @@ import java.util.OptionalLong;
 import java.util.SimpleTimeZone;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
+import org.apache.cxf.common.util.StringUtils;
 
 import static org.junit.Assert.assertEquals;
 
@@ -109,8 +112,44 @@ public class JsonbTypesTest {
         assertEquals(expected, jsonb.toJson(types));
     }
 
+    @Test
+    public void readAndWriteWithDateFormats() {
+        
readAndWriteWithDateFormat(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"),
 "yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+        
readAndWriteWithDateFormat(DateTimeFormatter.ofPattern("yyyyMMdd+HHmmssZ"), 
"yyyyMMdd+HHmmssZ");
+        readAndWriteWithDateFormat(DateTimeFormatter.ofPattern("yyyy-MM-dd"), 
"yyyy-MM-dd");
+    }
+    
+    private void readAndWriteWithDateFormat(DateTimeFormatter 
dateTimeFormatter, String dateFormat) {
+        final LocalDate localDate = LocalDate.of(2015, 1, 1);
+        final LocalDateTime localDateTime = LocalDateTime.of(2015, 1, 1, 1, 1);
+        final ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, 
ZoneId.of("UTC"));
+        final String expected = "{" +
+            "\"calendar\":\"" + dateTimeFormatter.format(zonedDateTime) + 
"\"," +
+            "\"date\":\"" + 
dateTimeFormatter.format(ZonedDateTime.ofInstant(localDateTime.toInstant(ZoneOffset.UTC),
 ZoneId.of("UTC"))) + "\"," +
+            "\"gregorianCalendar\":\"" + 
dateTimeFormatter.format(zonedDateTime) + "\"," +
+            "\"instant\":\"" + 
dateTimeFormatter.format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(TimeUnit.DAYS.toMillis(localDate.toEpochDay())),
 ZoneId.of("UTC"))) + "\"," +
+            "\"localDate\":\"" + 
dateTimeFormatter.format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(TimeUnit.DAYS.toMillis(localDate.toEpochDay())),
 ZoneId.of("UTC"))) + "\"," +
+            "\"localDateTime\":\"" + 
dateTimeFormatter.format(ZonedDateTime.ofInstant(localDateTime.toInstant(ZoneOffset.UTC),
 ZoneId.of("UTC"))) + "\"," +
+            "\"offsetDateTime\":\"" + 
dateTimeFormatter.format(ZonedDateTime.ofInstant(OffsetDateTime.of(localDateTime,
 ZoneOffset.UTC).toInstant(), ZoneId.of("UTC"))) + "\"" +
+            "}";
+
+        final Jsonb jsonb = newJsonb(dateFormat);
+        
+        final DateTypes types = jsonb.fromJson(new StringReader(expected), 
DateTypes.class);
+        assertEquals(localDate, types.localDate);
+        assertEquals(expected, jsonb.toJson(types));
+    }
+    
     private static Jsonb newJsonb() {
-        return JsonbProvider.provider().create().withConfig(new 
JsonbConfig().setProperty("johnzon.attributeOrder", new Comparator<String>() {
+        return newJsonb(null);
+    }
+    
+    private static Jsonb newJsonb(String dateFormat) {
+        JsonbConfig jsonbConfig = new JsonbConfig();
+        if (!StringUtils.isEmpty(dateFormat)){
+            jsonbConfig.withDateFormat(dateFormat, Locale.getDefault());
+        }
+        return 
JsonbProvider.provider().create().withConfig(jsonbConfig.setProperty("johnzon.attributeOrder",
 new Comparator<String>() {
             @Override
             public int compare(final String o1, final String o2) {
                 return o1.compareTo(o2);
@@ -339,4 +378,97 @@ public class JsonbTypesTest {
                 period, localDateTime, localDate, offsetDateTime, offsetTime);
         }
     }
+
+    public static class DateTypes {
+        private Date date;
+        private Calendar calendar;
+        private GregorianCalendar gregorianCalendar;
+        private Instant instant;
+        private LocalDateTime localDateTime;
+        private LocalDate localDate;
+        private OffsetDateTime offsetDateTime;
+
+
+        public Date getDate() {
+            return date;
+        }
+
+        public void setDate(Date date) {
+            this.date = date;
+        }
+
+        public Calendar getCalendar() {
+            return calendar;
+        }
+
+        public void setCalendar(Calendar calendar) {
+            this.calendar = calendar;
+        }
+
+        public GregorianCalendar getGregorianCalendar() {
+            return gregorianCalendar;
+        }
+
+        public void setGregorianCalendar(GregorianCalendar gregorianCalendar) {
+            this.gregorianCalendar = gregorianCalendar;
+        }
+
+        public Instant getInstant() {
+            return instant;
+        }
+
+        public void setInstant(Instant instant) {
+            this.instant = instant;
+        }
+
+        public LocalDateTime getLocalDateTime() {
+            return localDateTime;
+        }
+
+        public void setLocalDateTime(LocalDateTime localDateTime) {
+            this.localDateTime = localDateTime;
+        }
+
+        public LocalDate getLocalDate() {
+            return localDate;
+        }
+
+        public void setLocalDate(LocalDate localDate) {
+            this.localDate = localDate;
+        }
+
+        public OffsetDateTime getOffsetDateTime() {
+            return offsetDateTime;
+        }
+
+        public void setOffsetDateTime(OffsetDateTime offsetDateTime) {
+            this.offsetDateTime = offsetDateTime;
+        }
+
+
+        @Override
+        public boolean equals(final Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            final Types types = Types.class.cast(o);
+            return 
+                Objects.equals(date, types.date) &&
+                Objects.equals(calendar, types.calendar) &&
+                Objects.equals(gregorianCalendar, types.gregorianCalendar) &&
+                Objects.equals(instant, types.instant) &&
+                Objects.equals(localDateTime, types.localDateTime) &&
+                Objects.equals(localDate, types.localDate) &&
+                Objects.equals(offsetDateTime, types.offsetDateTime);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(
+                date, calendar, gregorianCalendar, instant, localDateTime, 
localDate, offsetDateTime);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java
index 7ec37c1..f16e2c4 100644
--- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java
@@ -24,6 +24,9 @@ import javax.json.bind.Jsonb;
 import javax.json.bind.annotation.JsonbDateFormat;
 import javax.json.bind.annotation.JsonbProperty;
 import javax.json.bind.spi.JsonbProvider;
+
+import java.io.ByteArrayOutputStream;
+import java.io.StringWriter;
 import java.time.LocalDateTime;
 import java.util.Collection;
 import java.util.HashMap;
@@ -34,6 +37,35 @@ import static org.junit.Assert.assertEquals;
 
 public class JsonbWriteTest {
     @Test
+    public void boolAsString() {
+        assertEquals("true", 
JsonbProvider.provider().create().build().toJson(Boolean.TRUE));
+    }
+
+    @Test
+    public void boolAsStringWriter() {
+        StringWriter sw = new StringWriter();
+        JsonbProvider.provider().create().build().toJson(Boolean.TRUE,sw);
+        assertEquals("true", sw.toString());
+    }
+
+    @Test
+    public void boolAsStream() {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        JsonbProvider.provider().create().build().toJson(Boolean.TRUE, baos);
+        assertEquals("true", baos.toString());
+    }
+
+    @Test
+    public void boolAsStreamInObject() {
+        SimpleBool simple = new SimpleBool();
+        simple.setBool(Boolean.TRUE);
+
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        JsonbProvider.provider().create().build().toJson(simple, baos);
+        assertEquals("{\"bool\":true}", baos.toString());
+    }
+
+    @Test
     public void simple() {
         final Simple simple = new Simple();
         simple.setValue("test");
@@ -93,6 +125,19 @@ public class JsonbWriteTest {
         }
     }
 
+    public static class SimpleBool {
+        private Boolean bool;
+
+        public Boolean getBool() {
+            return bool;
+        }
+
+        public SimpleBool setBool(Boolean bool) {
+            this.bool = bool;
+            return this;
+        }
+    }
+
     public static class SimpleProperty {
         @JsonbProperty("simple")
         private String value;

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ObjectSerializationTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ObjectSerializationTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ObjectSerializationTest.java
new file mode 100644
index 0000000..7ad703c
--- /dev/null
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ObjectSerializationTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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 java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+
+import org.junit.Test;
+
+public class ObjectSerializationTest {
+    private final Jsonb mapper = JsonbBuilder.create();
+
+    @Test
+    public void primitiveBoolean() {
+        assertEquals("{\"data\":true}", toJson(new Wrapper(true)));
+    }
+
+    @Test
+    public void numberBoolean() {
+        assertEquals("{\"data\":1}", toJson(new Wrapper(1)));
+    }
+
+    @Test
+    public void stringBoolean() {
+        assertEquals("{\"data\":\"ok\"}", toJson(new Wrapper("ok")));
+    }
+
+    @Test
+    public void objectBoolean() {
+        assertEquals("{\"data\":{\"data\":\"ok\"}}", toJson(new Wrapper(new 
Wrapper("ok"))));
+    }
+
+    @Test
+    public void arrayString() {
+        assertEquals("{\"data\":[\"10\",\"2\"]}", toJson(new 
Wrapper(asList("10", "2"))));
+    }
+
+    @Test
+    public void nestedArrayString() {
+        assertEquals("{\"data\":{\"data\":[\"10\",\"2\"]}}", toJson(new 
Wrapper(new Wrapper(asList("10", "2")))));
+    }
+
+    private String toJson(final Wrapper wrapper) {
+        return mapper.toJson(wrapper);
+    }
+
+    public static class Wrapper {
+        private final Object data;
+
+        private Wrapper(final Object data) {
+            this.data = data;
+        }
+
+        public Object getData() {
+            return data;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java
----------------------------------------------------------------------
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 475fbcc..a6771ef 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
@@ -31,6 +31,8 @@ import javax.json.bind.serializer.SerializationContext;
 import javax.json.stream.JsonGenerator;
 import javax.json.stream.JsonParser;
 import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -41,19 +43,31 @@ public class SerializerTest {
     public void roundTrip() {
         final Jsonb jsonb = JsonbBuilder.create();
 
-        final String json = 
"{\"foo\":{\"full\":true,\"name\":\"SerializerTest\"}}";
+        final String expectedJson = 
"{\"foo\":{\"full\":true,\"name\":\"SerializerTest\"},\"moreFoos\":[{\"full\":true,\"name\":\"foo2\"},{\"full\":true,\"name\":\"foo3\"}]}";
 
         final Foo foo = new Foo();
         foo.name = "SerializerTest";
         final Wrapper wrapper = new Wrapper();
         wrapper.foo = foo;
 
-        assertEquals(json, jsonb.toJson(wrapper));
+        Foo foo2 = new Foo();
+        foo2.name = "foo2";
+        Foo foo3 = new Foo();
+        foo3.name = "foo3";
+        wrapper.moreFoos.add(foo2);
+        wrapper.moreFoos.add(foo3);
 
-        final Wrapper deser = jsonb.fromJson(json, Wrapper.class);
+        assertEquals(expectedJson, jsonb.toJson(wrapper));
+
+        final Wrapper deser = jsonb.fromJson(expectedJson, Wrapper.class);
         assertEquals(foo.name, deser.foo.name);
         assertEquals(foo.name.length(), deser.foo.value);
         assertTrue(deser.foo.flag);
+
+        assertEquals(2, deser.moreFoos.size());
+        assertEquals("foo2", deser.moreFoos.get(0).name);
+        assertEquals(4, deser.moreFoos.get(0).value);
+        assertEquals(4, deser.moreFoos.get(1).value);
     }
 
     public static class Foo {
@@ -66,6 +80,10 @@ public class SerializerTest {
         @JsonbTypeSerializer(FooSer.class)
         @JsonbTypeDeserializer(FooDeser.class)
         public Foo foo;
+
+        @JsonbTypeSerializer(FooSer.class)
+        @JsonbTypeDeserializer(FooDeser.class)
+        public List<Foo> moreFoos = new ArrayList<>();
     }
 
     public static class FooDeser implements JsonbDeserializer<Foo> {

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java
----------------------------------------------------------------------
diff --git 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java
 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java
index d733447..91fca7d 100644
--- 
a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java
+++ 
b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java
@@ -41,31 +41,58 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.util.Arrays;
 import java.util.List;
 
 import static java.util.Arrays.asList;
 import static java.util.Collections.singletonList;
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.ws.rs.ext.ContextResolver;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 public class JsonbJaxRsTest {
     private final static String ENDPOINT_ADDRESS = "local://johnzon";
+    private final static String ENDPOINT_ADDRESS_JSONB_CONFIG = 
"local://johnzonjsonbconfig";
     private static Server server;
+    private static Server serverJsonbConfig;
 
+    public static class JsonBindingProvider implements ContextResolver<Jsonb> {
+
+        private final Jsonb jsonb = JsonbBuilder.create();
+        public static Boolean called = Boolean.FALSE;
+
+        @Override
+        public Jsonb getContext(Class<?> type) {
+            called = Boolean.TRUE;
+            return jsonb;
+        }
+
+    }
+    
     @BeforeClass
     public static void bindEndpoint() throws Exception {
-        final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
         sf.setResourceClasses(JohnzonResource.class);
         sf.setProviders(singletonList(new JsonbJaxrsProvider<>()));
         sf.setResourceProvider(JohnzonResource.class, new 
SingletonResourceProvider(new JohnzonResource(), false));
         sf.setAddress(ENDPOINT_ADDRESS);
         server = sf.create();
+        sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(JohnzonResource.class);
+        sf.setProviders(Arrays.asList(new JsonbJaxrsProvider<>(), new 
JsonBindingProvider()));
+        sf.setResourceProvider(JohnzonResource.class, new 
SingletonResourceProvider(new JohnzonResource(), false));
+        sf.setAddress(ENDPOINT_ADDRESS_JSONB_CONFIG);
+        serverJsonbConfig = sf.create();
     }
 
     @AfterClass
     public static void unbind() throws Exception {
         server.stop();
         server.destroy();
+        serverJsonbConfig.stop();
+        serverJsonbConfig.destroy();
     }
 
     @Test
@@ -75,6 +102,12 @@ public class JsonbJaxRsTest {
     }
 
     @Test
+    public void jsonbconfigProvider() {
+        client(ENDPOINT_ADDRESS_JSONB_CONFIG, 
MediaType.APPLICATION_JSON_TYPE).path("johnzon").get(String.class);
+        assertEquals(JsonBindingProvider.called, Boolean.TRUE);
+    }
+    
+    @Test
     public void object() {
         final String output = client().path("johnzon").get(String.class);
         assertEquals("{\"name\":\"johnzon\"}", output);
@@ -149,7 +182,11 @@ public class JsonbJaxRsTest {
     }
 
     private static WebClient client(final MediaType mediaType) {
-        final WebClient client = WebClient.create(ENDPOINT_ADDRESS, 
singletonList(new JsonbJaxrsProvider<>())).accept(mediaType);
+        return client(ENDPOINT_ADDRESS, mediaType);
+    }
+
+    private static WebClient client(final String endpoint, final MediaType 
mediaType) {
+        final WebClient client = WebClient.create(endpoint, singletonList(new 
JsonbJaxrsProvider<>())).accept(mediaType);
         
WebClient.getConfig(client).getRequestContext().put(LocalConduit.DIRECT_DISPATCH,
 Boolean.TRUE);
         return client;
     }

http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-mapper/pom.xml
----------------------------------------------------------------------
diff --git a/johnzon-mapper/pom.xml b/johnzon-mapper/pom.xml
index d28502a..cf16061 100644
--- a/johnzon-mapper/pom.xml
+++ b/johnzon-mapper/pom.xml
@@ -71,4 +71,18 @@
     
<staging.directory>${project.parent.reporting.outputDirectory}</staging.directory>
   </properties>
   <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            
<Export-Package>{local-packages};-split-package:=error,org.apache.johnzon.mapper.internal</Export-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
 </project>

Reply via email to