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 2015/12/08 10:49:59 UTC

incubator-johnzon git commit: simple value handling

Repository: incubator-johnzon
Updated Branches:
  refs/heads/master 55536f3ae -> a2d5d6023


simple value handling


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

Branch: refs/heads/master
Commit: a2d5d6023df38c648c3e06194ae43c593cf8ed4f
Parents: 55536f3
Author: Romain Manni-Bucau <rm...@gmail.com>
Authored: Tue Dec 8 10:50:49 2015 +0100
Committer: Romain Manni-Bucau <rm...@gmail.com>
Committed: Tue Dec 8 10:50:49 2015 +0100

----------------------------------------------------------------------
 .../org/apache/johnzon/core/JsonReaderImpl.java |  41 ++++-
 .../johnzon/core/JsonStreamParserImpl.java      |  16 +-
 .../org/apache/johnzon/core/JsonParserTest.java |  42 ++++++
 .../apache/johnzon/core/JsonReaderImplTest.java |  32 ++++
 .../org/apache/johnzon/jsonb/JohnsonJsonb.java  | 149 ++++++++++++++++---
 .../johnzon/jsonb/DefaultMappingTest.java       | 112 +++++++-------
 .../johnzon/mapper/JohnzonReaderHandler.java    |  35 +++++
 .../java/org/apache/johnzon/mapper/Mapper.java  |  45 +++++-
 .../apache/johnzon/mapper/ReaderHandler.java    |  45 ++++++
 .../johnzon/mapper/MapperEnhancedTest.java      |   2 +-
 .../org/apache/johnzon/mapper/MapperTest.java   |   2 +-
 11 files changed, 426 insertions(+), 95 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
index bba027c..d4719b9 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderImpl.java
@@ -20,14 +20,16 @@ package org.apache.johnzon.core;
 
 import javax.json.JsonArray;
 import javax.json.JsonArrayBuilder;
+import javax.json.JsonNumber;
 import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 import javax.json.JsonReader;
 import javax.json.JsonStructure;
+import javax.json.JsonValue;
 import javax.json.stream.JsonParser;
 import javax.json.stream.JsonParsingException;
 
-class JsonReaderImpl implements JsonReader {
+public class JsonReaderImpl implements JsonReader {
     private final JsonParser parser;
     private boolean closed = false;
 
@@ -37,7 +39,11 @@ class JsonReaderImpl implements JsonReader {
 
     @Override
     public JsonStructure read() {
+        return JsonStructure.class.cast(readValue());
+    }
 
+    //@Override
+    public JsonValue readValue() {
         checkClosed();
 
         if (!parser.hasNext()) {
@@ -61,11 +67,42 @@ class JsonReaderImpl implements JsonReader {
                 }
                 close();
                 return arrayBuilder.build();
+            case VALUE_STRING:
+                if (parser.hasNext()) {
+                    throw new JsonParsingException("Expected end of file", parser.getLocation());
+                }
+                final JsonStringImpl string = new JsonStringImpl(parser.getString());
+                close();
+                return string;
+            case VALUE_FALSE:
+                if (parser.hasNext()) {
+                    throw new JsonParsingException("Expected end of file", parser.getLocation());
+                }
+                close();
+                return JsonValue.FALSE;
+            case VALUE_TRUE:
+                if (parser.hasNext()) {
+                    throw new JsonParsingException("Expected end of file", parser.getLocation());
+                }
+                close();
+                return JsonValue.TRUE;
+            case VALUE_NULL:
+                if (parser.hasNext()) {
+                    throw new JsonParsingException("Expected end of file", parser.getLocation());
+                }
+                close();
+                return JsonValue.NULL;
+            case VALUE_NUMBER:
+                if (parser.hasNext()) {
+                    throw new JsonParsingException("Expected end of file", parser.getLocation());
+                }
+                final JsonNumber number = new JsonNumberImpl(parser.getBigDecimal());
+                close();
+                return number;
             default:
                 close();
                 throw new JsonParsingException("Unknown structure: " + next, parser.getLocation());
         }
-
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java
index 89e5752..2f40a21 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java
@@ -95,8 +95,8 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{
 
     //minimal stack implementation
     private static final class StructureElement {
-        final StructureElement previous;
-        final boolean isArray;
+        private final StructureElement previous;
+        private final boolean isArray;
 
         StructureElement(final StructureElement previous, final boolean isArray) {
             super();
@@ -174,7 +174,11 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{
     @Override
     public final boolean hasNext() {
 
-        if (currentStructureElement != null || (previousEvent != END_ARRAY && previousEvent != END_OBJECT) || previousEvent == 0) {
+        if (currentStructureElement != null ||
+            (previousEvent != END_ARRAY && previousEvent != END_OBJECT &&
+                previousEvent != VALUE_STRING && previousEvent != VALUE_FALSE && previousEvent != VALUE_TRUE && previousEvent != VALUE_NULL && previousEvent != VALUE_NUMBER) ||
+            previousEvent == 0) {
+
             return true;
         }
 
@@ -648,7 +652,7 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{
         } else { //Event is  START_OBJECT  OR START_ARRAY OR COMMA_EVENT
             //must be a key if we are in an object, if not its a value 
 
-            if (currentStructureElement != null && currentStructureElement.isArray) {
+            if ((currentStructureElement != null && currentStructureElement.isArray) || currentStructureElement == null) {
                 return EVT_MAP[previousEvent = VALUE_STRING];
             }
 
@@ -728,9 +732,9 @@ public class JsonStreamParserImpl implements JsonChars, JsonParser{
 
         }
 
-        endOfValueInBuffer = bufferPos;
+        endOfValueInBuffer = y == EOF && endOfValueInBuffer < 0 ? -1 : bufferPos;
 
-        if (y == COMMA_CHAR || y == END_ARRAY_CHAR || y == END_OBJECT_CHAR || y == EOL || y == SPACE || y == TAB || y == CR) {
+        if (y == COMMA_CHAR || y == END_ARRAY_CHAR || y == END_OBJECT_CHAR || y == EOL || y == SPACE || y == TAB || y == CR || y == EOF) {
 
             bufferPos--;//unread one char
 

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
index 0ffbd6d..e035789 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java
@@ -1637,20 +1637,26 @@ public class JsonParserTest {
         }
     }
 
+    /*
     @Test(expected=JsonParsingException.class)
     public void rfc7159MustFailForLiteral() {
         Json.createReader(new ByteArrayInputStream("null ".getBytes())).read();
     }
+    */
 
+    /*
     @Test(expected=JsonParsingException.class)
     public void rfc7159MustFailForString() {
         Json.createReader(new ByteArrayInputStream("\"hello\"".getBytes())).read();
     }
+    */
 
+    /*
     @Test(expected=JsonParsingException.class)
     public void rfc7159MustFailForNumber() {
         Json.createReader(new ByteArrayInputStream("  12  ".getBytes())).read();
     }
+    */
 
     @Test(expected=JsonParsingException.class)
     public void arrayFollowedByGarbage() {
@@ -1806,6 +1812,42 @@ public class JsonParserTest {
         }
     }
 
+    @Test
+    public void plainValues() {
+        { // string
+            final JsonParser string = Json.createParser(new StringReader("\"a\""));
+            assertTrue(string.hasNext());
+            assertEquals(Event.VALUE_STRING, string.next());
+            assertEquals("a", string.getString());
+            assertFalse(string.hasNext());
+        }
+        { // true
+            final JsonParser parser = Json.createParser(new StringReader("true"));
+            assertTrue(parser.hasNext());
+            assertEquals(Event.VALUE_TRUE, parser.next());
+            assertFalse(parser.hasNext());
+        }
+        { // false
+            final JsonParser parser = Json.createParser(new StringReader("false"));
+            assertTrue(parser.hasNext());
+            assertEquals(Event.VALUE_FALSE, parser.next());
+            assertFalse(parser.hasNext());
+        }
+        { // null
+            final JsonParser parser = Json.createParser(new StringReader("null"));
+            assertTrue(parser.hasNext());
+            assertEquals(Event.VALUE_NULL, parser.next());
+            assertFalse(parser.hasNext());
+        }
+        { // number
+            final JsonParser parser = Json.createParser(new StringReader("1234"));
+            assertTrue(parser.hasNext());
+            assertEquals(Event.VALUE_NUMBER, parser.next());
+            assertEquals(1234, parser.getInt());
+            assertFalse(parser.hasNext());
+        }
+    }
+
     class AttemptingInputStream extends ByteArrayInputStream {
 
         public AttemptingInputStream(byte[] buf) {

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java
index 3dc13cc..e9d3d74 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonReaderImplTest.java
@@ -35,10 +35,13 @@ import java.util.Map;
 
 import javax.json.Json;
 import javax.json.JsonArray;
+import javax.json.JsonNumber;
 import javax.json.JsonObject;
 import javax.json.JsonReader;
 import javax.json.JsonReaderFactory;
+import javax.json.JsonString;
 import javax.json.JsonStructure;
+import javax.json.JsonValue;
 
 import org.junit.Test;
 
@@ -526,4 +529,33 @@ public class JsonReaderImplTest {
             }
         }
     }
+
+    @Test
+    public void simpleValues() {
+        { // string
+            final JsonValue value = JsonReaderImpl.class.cast(Json.createReader(new StringReader("\"a string\""))).readValue();
+            assertEquals(JsonValue.ValueType.STRING, value.getValueType());
+            assertEquals("a string", JsonString.class.cast(value).getString());
+        }
+        { // true
+            final JsonValue value = JsonReaderImpl.class.cast(Json.createReader(new StringReader("true"))).readValue();
+            assertEquals(JsonValue.ValueType.TRUE, value.getValueType());
+            assertEquals(JsonValue.TRUE, value);
+        }
+        { // false
+            final JsonValue value = JsonReaderImpl.class.cast(Json.createReader(new StringReader("false"))).readValue();
+            assertEquals(JsonValue.ValueType.FALSE, value.getValueType());
+            assertEquals(JsonValue.FALSE, value);
+        }
+        { // null
+            final JsonValue value = JsonReaderImpl.class.cast(Json.createReader(new StringReader("null"))).readValue();
+            assertEquals(JsonValue.ValueType.NULL, value.getValueType());
+            assertEquals(JsonValue.NULL, value);
+        }
+        { // number
+            final JsonValue value = JsonReaderImpl.class.cast(Json.createReader(new StringReader("1234.5"))).readValue();
+            assertEquals(JsonValue.ValueType.NUMBER, value.getValueType());
+            assertEquals(1234.5, JsonNumber.class.cast(value).doubleValue(), 0.);
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
index ec5e960..7088372 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
@@ -37,7 +37,12 @@ import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.nio.CharBuffer;
 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 JohnsonJsonb implements Jsonb {
     private final Mapper delegate;
 
@@ -53,12 +58,54 @@ public class JohnsonJsonb implements Jsonb {
             } else if (Collection.class.isAssignableFrom(type)) {
                 return (T) delegate.readCollection(new StringReader(str), new JohnzonParameterizedType(type, Object.class));
             }
-            return delegate.readObject(str, type);
+            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 {
@@ -68,7 +115,12 @@ public class JohnsonJsonb implements Jsonb {
             } else if (isCollection(runtimeType)) {
                 return (T) delegate.readCollection(new StringReader(str), ParameterizedType.class.cast(runtimeType));
             }
-            return delegate.readObject(str, 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);
         }
@@ -82,7 +134,12 @@ public class JohnsonJsonb implements Jsonb {
             } else if (Collection.class.isAssignableFrom(type)) {
                 return (T) delegate.readCollection(toReader(readable), new JohnzonParameterizedType(type, Object.class));
             }
-            return delegate.readObject(toReader(readable), type);
+            final Type mappingType = unwrapPrimitiveOptional(type);
+            final Object object = delegate.readObject(toReader(readable), mappingType);
+            if (mappingType != type) {
+                return wrapPrimitiveOptional(object, type);
+            }
+            return (T) object;
         } catch (final MapperException me) {
             throw new JsonbException(me.getMessage(), me);
         }
@@ -90,13 +147,22 @@ public class JohnsonJsonb implements Jsonb {
 
     @Override
     public <T> T fromJson(final Readable readable, final Type runtimeType) throws JsonbException {
-        if (isArray(runtimeType)) {
-            final Class<T> type = Class.class.cast(runtimeType);
-            return delegate.readTypedArray(toReader(readable), type.getComponentType(), type);
-        } else if (isCollection(runtimeType)) {
-            return (T) delegate.readCollection(toReader(readable), ParameterizedType.class.cast(runtimeType));
+        try {
+            if (isArray(runtimeType)) {
+                final Class<T> type = Class.class.cast(runtimeType);
+                return delegate.readTypedArray(toReader(readable), type.getComponentType(), type);
+            } else if (isCollection(runtimeType)) {
+                return (T) delegate.readCollection(toReader(readable), ParameterizedType.class.cast(runtimeType));
+            }
+            final Type mappingType = unwrapPrimitiveOptional(runtimeType);
+            final Object object = delegate.readObject(toReader(readable), mappingType);
+            if (mappingType != runtimeType) {
+                return wrapPrimitiveOptional(object, runtimeType);
+            }
+            return (T) object;
+        } catch (final MapperException me) {
+            throw new JsonbException(me.getMessage(), me);
         }
-        return delegate.readObject(toReader(readable), runtimeType);
     }
 
     @Override
@@ -107,7 +173,12 @@ public class JohnsonJsonb implements Jsonb {
             } else if (Collection.class.isAssignableFrom(type)) {
                 return (T) delegate.readCollection(stream, new JohnzonParameterizedType(type, Object.class));
             }
-            return delegate.readObject(stream, type);
+            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);
         }
@@ -122,15 +193,25 @@ public class JohnsonJsonb implements Jsonb {
             } else if (isCollection(runtimeType)) {
                 return (T) delegate.readCollection(stream, ParameterizedType.class.cast(runtimeType));
             }
-            return delegate.readObject(stream, 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 object) throws JsonbException {
+    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)) {
@@ -195,8 +276,9 @@ public class JohnsonJsonb implements Jsonb {
     }
 
     @Override
-    public String toJson(final Object object, final Type runtimeType) throws JsonbException {
-        if (isArray(runtimeType)) {
+    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));
@@ -205,8 +287,9 @@ public class JohnsonJsonb implements Jsonb {
     }
 
     @Override
-    public void toJson(final Object object, final Appendable appendable) throws JsonbException {
-        if (isArray(object.getClass())) {
+    public void toJson(final Object inObject, final Appendable appendable) throws JsonbException {
+        final Object object = unwrapOptional(inObject);
+        if (object != null && isArray(object.getClass())) {
             delegate.writeArray((Object[]) object, toWriter(appendable));
         } else if (Collection.class.isInstance(object)) {
             delegate.writeArray(Collection.class.cast(object), toWriter(appendable));
@@ -216,8 +299,9 @@ public class JohnsonJsonb implements Jsonb {
     }
 
     @Override
-    public void toJson(final Object object, final Type runtimeType, final Appendable appendable) throws JsonbException {
-        if (isArray(runtimeType)) {
+    public void toJson(final Object inObject, final Type runtimeType, final Appendable appendable) throws JsonbException {
+        final Object object = unwrapOptional(inObject);
+        if (object != null && isArray(runtimeType)) {
             delegate.writeArray((Object[]) object, toWriter(appendable));
         } else if (isCollection(runtimeType)) {
             delegate.writeArray(Collection.class.cast(object), toWriter(appendable));
@@ -227,8 +311,9 @@ public class JohnsonJsonb implements Jsonb {
     }
 
     @Override
-    public void toJson(final Object object, final OutputStream stream) throws JsonbException {
-        if (isArray(object.getClass())) {
+    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);
@@ -238,8 +323,9 @@ public class JohnsonJsonb implements Jsonb {
     }
 
     @Override
-    public void toJson(final Object object, final Type runtimeType, final OutputStream stream) throws JsonbException {
-        if (isArray(runtimeType)) {
+    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);
@@ -248,6 +334,25 @@ public class JohnsonJsonb implements Jsonb {
         }
     }
 
+    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();
     }

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/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 518f8c8..5c99371 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
@@ -18,6 +18,7 @@
  */
 package org.apache.johnzon.jsonb;
 
+import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType;
 import org.junit.Ignore;
 import org.junit.Test;
 
@@ -46,6 +47,9 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.OptionalDouble;
+import java.util.OptionalInt;
+import java.util.OptionalLong;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -144,6 +148,55 @@ public class DefaultMappingTest {
         fromJsonAccessors();
     }
 
+    @Test
+    public void simpleValues() {
+        assertEquals("\"strValue\"", JSONB.toJson("\"strValue\""));
+        assertEquals("true", JSONB.toJson("true"));
+        assertEquals("false", JSONB.toJson("false"));
+        assertEquals("null", JSONB.toJson("null"));
+        assertEquals("strValue", JSONB.toJson(Optional.of("strValue")));
+        assertEquals("null", JSONB.toJson(Optional.ofNullable(null)));
+        assertEquals("null", JSONB.toJson(Optional.empty()));
+        assertEquals("1", JSONB.toJson(OptionalInt.of(1)));
+        assertEquals("null", JSONB.toJson(OptionalInt.empty()));
+        assertEquals("123", JSONB.toJson(OptionalLong.of(123)));
+        assertEquals("null", JSONB.toJson(OptionalLong.empty()));
+        assertEquals("1.2", JSONB.toJson(OptionalDouble.of(1.2)));
+        assertEquals("null", JSONB.toJson(OptionalDouble.empty()));
+
+        //Optional
+        Optional<String> stringValue = JSONB.fromJson("\"optionalString\"", new JohnzonParameterizedType(Optional.class, String.class));
+        assertTrue(stringValue.isPresent());
+        assertEquals("optionalString", stringValue.get());
+
+        Optional<String> nullStringValue = JSONB.fromJson("null", new JohnzonParameterizedType(Optional.class, String.class));
+        assertTrue(!nullStringValue.isPresent());
+
+        //OptionalInt
+        OptionalInt optionalInt = JSONB.fromJson("1", OptionalInt.class);
+        assertTrue(optionalInt.isPresent());
+        assertTrue(optionalInt.getAsInt() == 1);
+
+        OptionalInt emptyOptionalInt = JSONB.fromJson("null", OptionalInt.class);
+        assertTrue(!emptyOptionalInt.isPresent());
+
+        //OptionalLong
+        OptionalLong optionalLong = JSONB.fromJson("123", OptionalLong.class);
+        assertTrue(optionalLong.isPresent());
+        assertTrue(optionalLong.getAsLong() == 123L);
+
+        OptionalLong emptyOptionalLong = JSONB.fromJson("null", OptionalLong.class);
+        assertTrue(!emptyOptionalLong.isPresent());
+
+        //OptionalDouble
+        OptionalDouble optionalDouble = JSONB.fromJson("1.2", OptionalDouble.class);
+        assertTrue(optionalDouble.isPresent());
+        assertTrue(optionalDouble.getAsDouble() == 1.2);
+
+        OptionalDouble emptyOptionalDouble = JSONB.fromJson("null", OptionalDouble.class);
+        assertTrue(!emptyOptionalDouble.isPresent());
+    }
+
     public static void fromJsonPrimitives() {
         //String
         String str = JSONB.fromJson("\"some_string\"", String.class);
@@ -308,7 +361,7 @@ public class DefaultMappingTest {
         assertNotNull(JSONB.fromJson("[{\"value\":\"first\"},{\"value\":\"second\"}]", JsonArray.class));
 
         //JsonValue
-        // TBD assertNotNull(JSONB.fromJson("1", JsonValue.class));
+        assertNotNull(JSONB.fromJson("1", JsonValue.class));
     }
 
     public static void toJsonStructures() {
@@ -1079,29 +1132,6 @@ public class DefaultMappingTest {
     }
 
     public static void toJsonOptional() {
-
-        //Optional
-        /* TBD: direct mapping
-        assertEquals("\"strValue\"", JSONB.toJson(Optional.of("strValue")));
-
-
-        assertEquals("null", JSONB.toJson(Optional.ofNullable(null)));
-
-        assertEquals("null", JSONB.toJson(Optional.empty()));
-
-        //OptionalInt
-        assertEquals("1", JSONB.toJson(OptionalInt.of(1)));
-        assertEquals("null", JSONB.toJson(OptionalInt.empty()));
-
-        //OptionalLong
-        assertEquals("123", JSONB.toJson(OptionalLong.of(123)));
-        assertEquals("null", JSONB.toJson(OptionalLong.empty()));
-
-        //OptionalDouble
-        assertEquals("1.2", JSONB.toJson(OptionalDouble.of(1.2)));
-        assertEquals("null", JSONB.toJson(OptionalDouble.empty()));
-        */
-
         final OptionalClass object = new OptionalClass();
         object.optionalField = Optional.of("test");
         assertEquals("{\"optionalField\":\"test\"}", JSONB.toJson(object));
@@ -1118,40 +1148,6 @@ public class DefaultMappingTest {
     }
 
     public static void fromJsonOptional() {
-        /* TBD
-        //Optional
-        Optional<String> stringValue = JSONB.fromJson("\"optionalString\"", Optional.class);
-        assertTrue(stringValue.isPresent());
-        assertEquals("optionalString", stringValue.get());
-
-        Optional<String> nullStringValue = JSONB.fromJson("null", Optional.class);
-        assertTrue(!nullStringValue.isPresent());
-
-        //OptionalInt
-        OptionalInt optionalInt = JSONB.fromJson("1", OptionalInt.class);
-        assertTrue(optionalInt.isPresent());
-        assertTrue(optionalInt.getAsInt() == 1);
-
-        OptionalInt emptyOptionalInt = JSONB.fromJson("null", OptionalInt.class);
-        assertTrue(!emptyOptionalInt.isPresent());
-
-        //OptionalLong
-        OptionalLong optionalLong = JSONB.fromJson("123", OptionalLong.class);
-        assertTrue(optionalLong.isPresent());
-        assertTrue(optionalLong.getAsLong() == 123L);
-
-        OptionalLong emptyOptionalLong = JSONB.fromJson("null", OptionalLong.class);
-        assertTrue(!emptyOptionalLong.isPresent());
-
-        //OptionalDouble
-        OptionalDouble optionalDouble = JSONB.fromJson("1.2", OptionalDouble.class);
-        assertTrue(optionalDouble.isPresent());
-        assertTrue(optionalDouble.getAsDouble() == 1.2);
-
-        OptionalDouble emptyOptionalDouble = JSONB.fromJson("null", OptionalDouble.class);
-        assertTrue(!emptyOptionalDouble.isPresent());
-        */
-
         OptionalClass optionalClass = JSONB.fromJson("{\"optionalField\":\"value\"}", OptionalClass.class);
         assertTrue(optionalClass.optionalField.isPresent());
         assertEquals("value", optionalClass.optionalField.get());

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonReaderHandler.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonReaderHandler.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonReaderHandler.java
new file mode 100644
index 0000000..3aeec4d
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonReaderHandler.java
@@ -0,0 +1,35 @@
+/*
+ * 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.mapper;
+
+import org.apache.johnzon.core.JsonReaderImpl;
+
+import javax.json.JsonReader;
+import javax.json.JsonValue;
+
+// just for classloading
+public class JohnzonReaderHandler {
+    private JohnzonReaderHandler() {
+        // no-op
+    }
+
+    public static JsonValue read(final JsonReader reader) {
+        return JsonReaderImpl.class.cast(reader).readValue();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
index ac3e6b3..ea83813 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
@@ -95,6 +95,7 @@ public class Mapper {
     protected final boolean treatByteArrayAsBase64;
     protected final boolean treatByteArrayAsBase64URL;
     protected final Charset encoding;
+    protected final ReaderHandler readerHandler;
 
     // CHECKSTYLE:OFF
     public Mapper(final JsonReaderFactory readerFactory, final JsonGeneratorFactory generatorFactory,
@@ -113,6 +114,7 @@ public class Mapper {
         this.treatByteArrayAsBase64 = treatByteArrayAsBase64;
         this.treatByteArrayAsBase64URL = treatByteArrayAsBase64URL;
         this.encoding = encoding;
+        this.readerHandler = ReaderHandler.create(readerFactory);
     }
 
     private static JsonGenerator writePrimitives(final JsonGenerator generator, final Object value) {
@@ -294,9 +296,9 @@ public class Mapper {
     }
 
     public void writeObject(final Object object, final Writer stream) {
-        if (JsonValue.class.isInstance(object)) {
+        if (JsonValue.class.isInstance(object) || String.class.isInstance(object) || Number.class.isInstance(object) || object == null) {
             try {
-                stream.write(object.toString());
+                stream.write(String.valueOf(object));
             } catch (final IOException e) {
                 throw new MapperException(e);
             } finally {
@@ -555,11 +557,44 @@ public class Mapper {
 
     private <T> T mapObject(final Type clazz, final JsonReader reader) {
         try {
-            final JsonObject object = reader.readObject();
-            if (JsonStructure.class == clazz || JsonObject.class == clazz) {
+            final JsonValue object = readerHandler.read(reader);
+            if (JsonStructure.class == clazz || JsonObject.class == clazz || JsonValue.class == clazz) {
                 return (T) object;
             }
-            return (T) buildObject(clazz, object);
+            if (JsonObject.class.isInstance(object)) {
+                return (T) buildObject(clazz, JsonObject.class.cast(object));
+            }
+            if (JsonString.class.isInstance(object) && clazz == String.class) {
+                return (T) JsonString.class.cast(object).getString();
+            }
+            if (JsonNumber.class.isInstance(object)) {
+                final JsonNumber number = JsonNumber.class.cast(object);
+                if (clazz == int.class || clazz == Integer.class) {
+                    return (T) Integer.valueOf(number.intValue());
+                }
+                if (clazz == long.class || clazz == Long.class) {
+                    return (T) Long.valueOf(number.longValue());
+                }
+                if (clazz == double.class || clazz == Double.class) {
+                    return (T) Double.valueOf(number.doubleValue());
+                }
+                if (clazz == BigDecimal.class) {
+                    return (T) number.bigDecimalValue();
+                }
+                if (clazz == BigInteger.class) {
+                    return (T) number.bigIntegerValue();
+                }
+            }
+            if (JsonValue.NULL == object) {
+                return null;
+            }
+            if (JsonValue.TRUE == object && (Boolean.class == clazz || boolean.class == clazz)) {
+                return (T) Boolean.TRUE;
+            }
+            if (JsonValue.FALSE == object && (Boolean.class == clazz || boolean.class == clazz)) {
+                return (T) Boolean.FALSE;
+            }
+            throw new IllegalArgumentException("Unsupported " + object + " for type " + clazz);
         } catch (final Exception e) {
             throw new MapperException(e);
         } finally {

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ReaderHandler.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ReaderHandler.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ReaderHandler.java
new file mode 100644
index 0000000..42e272e
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ReaderHandler.java
@@ -0,0 +1,45 @@
+/*
+ * 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.mapper;
+
+import javax.json.JsonReader;
+import javax.json.JsonReaderFactory;
+import javax.json.JsonValue;
+
+public class ReaderHandler {
+    private final boolean johnzon;
+
+    private ReaderHandler(final boolean johnzon) {
+        this.johnzon = johnzon;
+    }
+
+    public static ReaderHandler create(final JsonReaderFactory readerFactory) {
+        if (readerFactory.getClass().getName().equals("org.apache.johnzon.core.JsonReaderFactoryImpl")) {
+            return new ReaderHandler(true);
+        }
+        return new ReaderHandler(false);
+    }
+
+    public JsonValue read(final JsonReader reader) {
+        if (johnzon) {
+            return JohnzonReaderHandler.read(reader);
+        }
+        return reader.read();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperEnhancedTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperEnhancedTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperEnhancedTest.java
index 30bbee5..8073136 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperEnhancedTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperEnhancedTest.java
@@ -46,7 +46,7 @@ public class MapperEnhancedTest {
     public void writeNull() {
         final StringWriter sw = new StringWriter();
         new MapperBuilder().build().writeObject(null, sw);
-        assertEquals("{}", sw.toString());
+        assertEquals("null", sw.toString());
     }
     
     @Test

http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/a2d5d602/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 d992725..b5c70a7 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
@@ -59,7 +59,7 @@ public class MapperTest {
     public void writeEmptyObject() {
         final StringWriter writer = new StringWriter();
         new MapperBuilder().build().writeObject(null, writer);
-        assertEquals("{}", writer.toString());
+        assertEquals("null", writer.toString());
     }
 
     @Test