first implementation version
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
index 60ede7e..bfdab90 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonArrayBuilderImpl.java
@@ -111,6 +111,31 @@
         
         tmpList.add(value);
     }
+    
+    
+    private void addValue(int index, JsonValue value){
+        if (value == null) {
+            throw npe();
+        }
+        
+        if(tmpList==null){
+            tmpList=new ArrayList<JsonValue>();
+        }
+        
+        tmpList.add(index, value);
+    }
+    
+    private void setValue(int index, JsonValue value){
+        if (value == null) {
+            throw npe();
+        }
+        
+        if(tmpList==null){
+            tmpList=new ArrayList<JsonValue>();
+        }
+        
+        tmpList.set(index, value);
+    }
 
     @Override
     public JsonArray build() {
@@ -130,146 +155,149 @@
     }
 
     @Override
-    public JsonArrayBuilder addAll(JsonArrayBuilder builder) {
-        tmpList.addAll(builder.build()); //TODO is it ok to call build() here and destry the builder?
+    public JsonArrayBuilder addAll(JsonArrayBuilder builder) {    	
+        addValue(builder.build()); //TODO is it ok to call build() here and destry the builder?
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, JsonValue value) {
-        tmpList.add(index, value);
+        addValue(index, value);
         return this;
         
     }
 
     @Override
     public JsonArrayBuilder add(int index, String value) {
-    	tmpList.add(index, Json.createValue(value));
+    	addValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, BigDecimal value) {
-    	tmpList.add(index, Json.createValue(value));
+    	addValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, BigInteger value) {
-    	tmpList.add(index, Json.createValue(value));
+    	addValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, int value) {
-    	tmpList.add(index, Json.createValue(value));
+    	addValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, long value) {
-    	tmpList.add(index, Json.createValue(value));
+    	addValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, double value) {
-    	tmpList.add(index, Json.createValue(value));
+    	addValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, boolean value) {
-    	tmpList.add(index, value?JsonValue.TRUE:JsonValue.FALSE);
+    	addValue(index, value?JsonValue.TRUE:JsonValue.FALSE);
         return this;
     }
 
     @Override
     public JsonArrayBuilder addNull(int index) {
-    	tmpList.add(index, JsonValue.NULL);
+    	addValue(index, JsonValue.NULL);
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, JsonObjectBuilder builder) {
-    	tmpList.add(index, builder.build()); //TODO ok to call build()?
+    	addValue(index, builder.build()); //TODO ok to call build()?
         return this;
     }
 
     @Override
     public JsonArrayBuilder add(int index, JsonArrayBuilder builder) {
-    	tmpList.add(index, builder.build()); //TODO ok to call build()?
+    	addValue(index, builder.build()); //TODO ok to call build()?
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, JsonValue value) {
-    	tmpList.set(index, value);
+    	setValue(index, value);
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, String value) {
-    	tmpList.set(index, Json.createValue(value));
+    	setValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, BigDecimal value) {
-    	tmpList.set(index, Json.createValue(value));
+    	setValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, BigInteger value) {
-    	tmpList.set(index, Json.createValue(value));
+    	setValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, int value) {
-    	tmpList.set(index, Json.createValue(value));
+    	setValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, long value) {
-    	tmpList.set(index, Json.createValue(value));
+    	setValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, double value) {
-    	tmpList.set(index, Json.createValue(value));
+    	setValue(index, Json.createValue(value));
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, boolean value) {
-    	tmpList.set(index, value?JsonValue.TRUE:JsonValue.FALSE);
+    	setValue(index, value?JsonValue.TRUE:JsonValue.FALSE);
         return this;
     }
 
     @Override
     public JsonArrayBuilder setNull(int index) {
-    	tmpList.set(index, JsonValue.NULL);
+    	setValue(index, JsonValue.NULL);
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, JsonObjectBuilder builder) {
-    	tmpList.set(index, builder.build()); //TODO ok here to call build?
+    	setValue(index, builder.build()); //TODO ok here to call build?
         return this;
     }
 
     @Override
     public JsonArrayBuilder set(int index, JsonArrayBuilder builder) {
-    	tmpList.set(index, builder.build()); //TODO ok here to call build?
+    	setValue(index, builder.build()); //TODO ok here to call build?
         return this;
     }
 
     @Override
     public JsonArrayBuilder remove(int index) {
+    	
+    	if(tmpList == null) return this;
+    	
         tmpList.remove(index);
         return this;
     }
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 fa54d07..40dd0a2 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
@@ -24,6 +24,7 @@
 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;
 
@@ -31,26 +32,37 @@
     private final JsonParser parser;
     private boolean closed = false;
     private final boolean readUntiltheEnd;
+    private final JsonParser.Event startEvent;
 
     JsonReaderImpl(final JsonParser parser) {
         this.parser = parser;
         this.readUntiltheEnd = true;
+        this.startEvent = null;
     }
     
-    JsonReaderImpl(final JsonParser parser, boolean readUntiltheEnd) {
+    JsonReaderImpl(final JsonParser parser, boolean readUntiltheEnd, JsonParser.Event startEvent) {
         this.parser = parser;
         this.readUntiltheEnd = readUntiltheEnd;
+        this.startEvent = startEvent;
     }
 
     @Override
     public JsonStructure read() {
+    	return (JsonStructure) read(true);
+    }
+    
+
+    private JsonValue read(boolean throwExceptionIfNotStructure) {
 
         checkClosed();
 
         if (!parser.hasNext()) {
             throw new IllegalStateException("Nothing to read");
         }
-        switch (parser.next()) {
+        
+        JsonParser.Event evt = startEvent==null?parser.next():startEvent;
+        
+        switch (evt) {
             case START_OBJECT:
                 final JsonObjectBuilder objectBuilder = new JsonObjectBuilderImpl();
                 parseObject(objectBuilder);
@@ -68,8 +80,19 @@
                 close();
                 return arrayBuilder.build();
             default:
-                close();
-                throw new JsonParsingException("Unknown structure: " + parser.next(), parser.getLocation());
+                if(throwExceptionIfNotStructure) {
+                	throw new JsonParsingException("Unknown structure: " + (parser.hasNext()?parser.next():"<EOF>"), parser.getLocation());
+                } else {
+                	try {
+						JsonValue value = parser.getValue();
+						if(parser.hasNext()) {
+							throw new JsonParsingException("Expected end of file", parser.getLocation());
+						}
+						return value;
+					} finally {
+		                close();
+					}
+                }
         }
 
     }
@@ -212,4 +235,11 @@
         }
 
     }
+
+	@Override
+	public JsonValue readValue() {
+		return read(false);
+	}
+    
+    
 }
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 b209378..1767122 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
@@ -38,6 +38,7 @@
 import javax.json.JsonException;
 import javax.json.JsonObject;
 import javax.json.JsonReaderFactory;
+import javax.json.JsonStructure;
 import javax.json.JsonValue;
 import javax.json.stream.JsonLocation;
 import javax.json.stream.JsonParser;
@@ -192,7 +193,8 @@
             if ((endOfValueInBuffer - startOfValueInBuffer) > maxValueLength) {
                 throw tmc();
             }
-
+//System.out.println("copy from "+startOfValueInBuffer+" with length "+(endOfValueInBuffer - startOfValueInBuffer));
+//System.out.println("endOfValueInBuffer "+endOfValueInBuffer);
             System.arraycopy(buffer, startOfValueInBuffer, fallBackCopyBuffer, fallBackCopyBufferLength,
                     (endOfValueInBuffer - startOfValueInBuffer));
             fallBackCopyBufferLength += (endOfValueInBuffer - startOfValueInBuffer);
@@ -505,7 +507,11 @@
         if (currentStructureElement == null) {
             currentStructureElement = new StructureElement(null, true);
         } else {
-            final StructureElement localStructureElement = new StructureElement(currentStructureElement, true);
+            if(!currentStructureElement.isArray && previousEvent != KEY_SEPARATOR_EVENT) {
+            	throw uexc("Expected \"");
+            }
+        	
+        	final StructureElement localStructureElement = new StructureElement(currentStructureElement, true);
             currentStructureElement = localStructureElement;
         }
 
@@ -763,7 +769,7 @@
 
         endOfValueInBuffer = 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
 
@@ -784,7 +790,11 @@
             if (fallBackCopyBufferLength > 0) {
 
                 //we crossed a buffer boundary, use value buffer
-                copyCurrentValue();
+                //copyCurrentValue();
+            	
+            	if (fallBackCopyBufferLength >= maxValueLength) {
+                    throw tmc();
+                }
 
             } else {
                 if ((endOfValueInBuffer - startOfValueInBuffer) >= maxValueLength) {
@@ -929,6 +939,8 @@
             }
         } else {
             //if there a content in the value buffer read from them, if not use main buffer
+        	//System.out.println(new String(fallBackCopyBuffer, 0,
+            //        fallBackCopyBufferLength));
             return (/*currentBigDecimalNumber = */fallBackCopyBufferLength > 0 ? new BigDecimal(fallBackCopyBuffer, 0,
                     fallBackCopyBufferLength) : new BigDecimal(buffer, startOfValueInBuffer, (endOfValueInBuffer - startOfValueInBuffer)));
         }
@@ -1022,12 +1034,12 @@
         return new IllegalStateException("Illegal parser state exception on " + location + ". Reason is [[" + message + "]]");
     }
 
-	@Override
-	public JsonObject getObject() {
-		JsonReaderImpl reader = new JsonReaderImpl(this, false);
-		JsonObject obj;
+    
+	private JsonStructure getStructure(Event start) {
+		JsonReaderImpl reader = new JsonReaderImpl(this, false, start);
+		JsonStructure obj;
 		try {
-			obj = reader.readObject();
+			obj = reader.read();
 		} catch (JsonParsingException e) {
 			throw is(e.getMessage());
 		} finally {
@@ -1036,6 +1048,22 @@
 
 		return obj;
 	}
+    
+	@Override
+	public JsonObject getObject() {
+		if(previousEvent != START_OBJECT) {
+			throw is("Parser state must be START_OBJECT");
+		}
+		return getStructure(Event.START_OBJECT).asJsonObject();
+	}
+	
+	@Override
+	public JsonArray getArray() {
+		if(previousEvent != START_ARRAY) {
+			throw is("Parser state must be START_ARRAY");
+		}
+		return getStructure(Event.START_ARRAY).asJsonArray();
+	}
 
 	@Override
 	public JsonValue getValue() {
@@ -1065,25 +1093,49 @@
 			return Json.createValue(getString());
 		}
 		
-		//never happen
-		return null;
-	}
-
-	@Override
-	public JsonArray getArray() {
-		JsonReaderImpl reader = new JsonReaderImpl(this, false);
-		JsonArray ar;
-		try {
-			ar = reader.readArray();
-		} catch (JsonParsingException e) {
-			throw is(e.getMessage());
-		} finally {
-			reader.close();
+		//
+		if(previousEvent == START_OBJECT) {
+			return getObject();
 		}
-
-		return ar;
+		
+		if(previousEvent == END_OBJECT) {
+			next();
+			return getValue();
+		}
+		
+		if(previousEvent == START_ARRAY) {
+			return getArray();
+		}
+		
+		if(previousEvent == END_ARRAY) {
+			next();
+			return getValue();
+		}
+		
+		if(previousEvent == KEY_NAME) {
+			return Json.createValue(getString());
+		}
+		
+		/* if(previousEvent == KEY_SEPARATOR_EVENT) {
+			next();
+			return getValue();
+		}
+		
+		if(previousEvent == COMMA_EVENT) {
+			next();
+			return getValue();
+		}*/
+		
+		/*if(previousEvent == -1) {
+			return getStructure();
+		}*/
+		
+		throw cust("Internal parsing error: Unknown state");
+	
 	}
 
+	
+
 	@Override
 	public Stream<JsonValue> getArrayStream() {
         //TODO check for beginning of an array
@@ -1132,7 +1184,7 @@
                      return false;
                  }
                  if (event != Event.KEY_NAME) {
-                     throw new JsonException("error generating stream, key name token expected");
+                     throw new JsonException("error generating stream, key name token expected (was: "+event+")");
                  }
                  String key = getString();
                  if (!hasNext()) {
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 451e182..f378b7a 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
@@ -33,15 +33,21 @@
 import java.nio.charset.Charset;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.function.Function;
+import java.util.stream.Stream;
 
 import javax.json.Json;
 import javax.json.JsonArray;
 import javax.json.JsonArrayBuilder;
 import javax.json.JsonException;
+import javax.json.JsonObject;
 import javax.json.JsonObjectBuilder;
 import javax.json.JsonReader;
+import javax.json.JsonString;
 import javax.json.JsonValue;
+import javax.json.stream.JsonCollectors;
 import javax.json.stream.JsonParser;
 import javax.json.stream.JsonParser.Event;
 import javax.json.stream.JsonParsingException;
@@ -1639,7 +1645,67 @@
     }
     
     @Test
+    public void simpleShortNumber() {
+        final JsonParser parser = Json.createParser(new StringReader("1"));
+        assertNotNull(parser);
+        assertTrue(parser.hasNext());
+        final JsonParser.Event event = parser.next();
+        assertNotNull(event);
+        assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+        assertEquals(Json.createValue(1), parser.getValue());
+        assertFalse(parser.hasNext());
+    }
+    
+    @Test
+    public void simpleENumber() {
+        final JsonParser parser = Json.createParser(new StringReader("-4.9e-4"));
+        assertNotNull(parser);
+        assertTrue(parser.hasNext());
+        final JsonParser.Event event = parser.next();
+        assertNotNull(event);
+        assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+        assertEquals(Json.createValue(new BigDecimal("-4.9e-4")), parser.getValue());
+        assertFalse(parser.hasNext());
+    }
+    
+    
+    @Test
+    public void simpleENumberMinBuffer() {
+    	
+    	for(int i=1; i<=10; i++) {
+    	final int bufflen=i;
+    	final JsonParser parser = Json.createParserFactory(new HashMap<String, Object>() {
+            {
+                put("org.apache.johnzon.default-char-buffer", bufflen);
+            }
+        }).createParser(new StringReader("-4.9e-4"));
+        assertNotNull(parser);
+        assertTrue(parser.hasNext());
+        final JsonParser.Event event = parser.next();
+        assertNotNull(event);
+        assertEquals(JsonParser.Event.VALUE_NUMBER, event);
+        assertEquals(Json.createValue(new BigDecimal("-4.9e-4")), parser.getValue());
+        assertFalse(parser.hasNext());
+        
+    	}
+    }
+    
+    
+    
+    @Test
     public void simpleValueTrue() {
+        final JsonParser parser = Json.createParser(new StringReader("true"));
+        assertNotNull(parser);
+        assertTrue(parser.hasNext());
+        final JsonParser.Event event = parser.next();
+        assertNotNull(event);
+        assertEquals(JsonParser.Event.VALUE_TRUE, event);
+        assertEquals(JsonValue.TRUE, parser.getValue());
+        assertFalse(parser.hasNext());
+    }
+    
+    @Test
+    public void simpleValueTrueWithWS() {
         final JsonParser parser = Json.createParser(new StringReader("  true"));
         assertNotNull(parser);
         assertTrue(parser.hasNext());
@@ -1763,31 +1829,33 @@
     
     @Test
     public void getObjectFromParser() {
-        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"b\":{\"c\":9, \"d\":10}, \"z\":8"));
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"b\":{\"c\":9, \"d\":10}, \"z\":8}"));
         assertNotNull(parser);
         parser.next();
         parser.next();
         parser.next();
         parser.next();
+        parser.next();
         assertEquals("{\"c\":9,\"d\":10}", parser.getObject().toString());
         assertTrue(parser.next() == Event.KEY_NAME);
     }
     
     @Test
     public void getObjectFromParserNested() {
-        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"b\":{\"c\":9, \"d\":10, \"r\":{\"q\":19, \"s\":144}}, \"z\":8"));
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"b\":{\"c\":9, \"d\":10, \"r\":{\"q\":19, \"s\":144}}, \"z\":8}"));
         assertNotNull(parser);
-        parser.next();
-        parser.next();
-        parser.next();
-        parser.next();
+        assertEquals(Event.START_OBJECT, parser.next());
+        assertEquals(Event.KEY_NAME, parser.next());
+        assertEquals(Event.VALUE_NUMBER, parser.next());
+        assertEquals(Event.KEY_NAME, parser.next());
+        assertEquals(Event.START_OBJECT, parser.next());
         assertEquals("{\"c\":9,\"d\":10,\"r\":{\"q\":19,\"s\":144}}", parser.getObject().toString());
         assertTrue(parser.next() == Event.KEY_NAME);
     }
     
     @Test(expected=IllegalStateException.class)
     public void getObjectFromParserWrongState() {
-        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"b\":{\"c\":9, \"d\":10}, \"z\":8"));
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"b\":{\"c\":9, \"d\":10}, \"z\":8}"));
         assertNotNull(parser);
         parser.next();
         parser.next();
@@ -1798,29 +1866,33 @@
     
     @Test
     public void getArrayFromParser() {
-        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, [1,2,3,4,5], \"z\":8"));
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"r\":[1,2,3,4,5], \"z\":8}"));
         assertNotNull(parser);
         parser.next();
         parser.next();
         parser.next();
+        parser.next();
+        parser.next();
         assertEquals("[1,2,3,4,5]", parser.getArray().toString());
         assertTrue(parser.next() == Event.KEY_NAME);
     }
     
     @Test
     public void getArrayFromParserNested() {
-        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, [1,2,3,4,5,[2,2,3,4,5]], \"z\":8"));
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"r\":[1,2,3,4,5,[2,2,3,4,5]], \"z\":8}"));
         assertNotNull(parser);
         parser.next();
         parser.next();
         parser.next();
+        parser.next();
+        parser.next();
         assertEquals("[1,2,3,4,5,[2,2,3,4,5]]", parser.getArray().toString());
         assertTrue(parser.next() == Event.KEY_NAME);
     }
     
     @Test(expected=IllegalStateException.class)
     public void getArrayFromParserWrogState() {
-        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, [1,2,3,4,5,[2,2,3,4,5]], \"z\":8"));
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, [1,2,3,4,5,[2,2,3,4,5]], \"z\":8}"));
         assertNotNull(parser);
         parser.next();
         parser.next();
@@ -1830,7 +1902,7 @@
     
     @Test
     public void skipObject() {
-        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"b\":{\"c\":9, \"d\":10, \"r\":{\"q\":19, \"s\":144}}, \"z\":8"));
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"b\":{\"c\":9, \"d\":10, \"r\":{\"q\":19, \"s\":144}}, \"z\":8}"));
         assertNotNull(parser);
         parser.next();
         parser.next();
@@ -1845,18 +1917,90 @@
     
     @Test
     public void skipArray() {
-        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, [1,2,3,4,5,[2,2,3,4,5]], \"z\":8"));
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"r\": [1,2,3,4,5,[2,2,3,4,5]], \"z\":8}"));
         assertNotNull(parser);
         parser.next();
         parser.next();
         parser.next();
         parser.next();
+        parser.next();
         parser.skipArray();
         parser.next();
-        assertTrue(parser.next() == Event.KEY_NAME);
+        assertEquals(Event.KEY_NAME, parser.next());
         assertEquals("z",parser.getString());
     }
     
+    @Test(expected=JsonParsingException.class)
+    public void invalidArray() {
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, [1,2,3,4,5,[2,2,3,4,5]], \"z\":8}"));
+        assertNotNull(parser);
+        assertTrue(parser.next() == Event.START_OBJECT);
+        assertTrue(parser.next() == Event.KEY_NAME);
+        assertTrue(parser.next() == Event.VALUE_NUMBER);
+        parser.next();
+    }
+    
+    @Test(expected=JsonParsingException.class)
+    public void invalidArrayMissingKeyname() {
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, :[1,2,3,4,5,[2,2,3,4,5]], \"z\":8}"));
+        assertNotNull(parser);
+        assertTrue(parser.next() == Event.START_OBJECT);
+        assertTrue(parser.next() == Event.KEY_NAME);
+        assertTrue(parser.next() == Event.VALUE_NUMBER);
+        parser.next();
+    }
+    
+    @Test(expected=JsonParsingException.class)
+    //TODO read key and : in once
+    public void invalidArrayMissingSeparator() {
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"a\"[1,2,3,4,5,[2,2,3,4,5]], \"z\":8}"));
+        assertNotNull(parser);
+        assertTrue(parser.next() == Event.START_OBJECT);
+        assertTrue(parser.next() == Event.KEY_NAME);
+        assertTrue(parser.next() == Event.VALUE_NUMBER);
+        assertTrue(parser.next() == Event.KEY_NAME);
+        parser.next();
+    }
+    
+    @Test
+    public void testGetValue() {
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":false, \"d\": {\"m\":6}, \"z\":true}"));
+        assertNotNull(parser);
+        parser.next();
+        JsonObject obj = parser.getValue().asJsonObject();
+        assertEquals(3, obj.size());
+    }
+    
+    @Test
+    public void testGetValue2() {
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":false, \"d\": {\"m\":6}, \"z\":true}"));
+        assertNotNull(parser);
+        assertEquals(Event.START_OBJECT, parser.next());
+        assertEquals(Event.KEY_NAME, parser.next());
+        JsonString obj = (JsonString) parser.getValue();
+        assertEquals("a", obj.getString());
+    }
+    
+    @Test
+    public void objectStream() {
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":false, \"d\": {\"m\":6}, \"z\":true}"));
+        assertNotNull(parser);
+        parser.next();
+        Stream<Map.Entry<String,JsonValue>> ostream = parser.getObjectStream();
+        assertEquals(3,ostream.count());
+        //System.out.println(parser.getValue());
+        
+    }
+    
+    @Test(expected=JsonParsingException.class)
+    public void missingClosingObject() {
+        final JsonParser parser = Json.createParser(new StringReader("{\"a\":5, \"d\": {\"m\":6}, \"z\":true"));
+        assertNotNull(parser);
+        while(parser.hasNext()) {
+        	parser.next();
+        }
+    }
+    
     class AttemptingInputStream extends ByteArrayInputStream {
 
         public AttemptingInputStream(byte[] buf) {
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java
new file mode 100644
index 0000000..fdb7ff8
--- /dev/null
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPatchTest.java
@@ -0,0 +1,50 @@
+package org.apache.johnzon.core;
+
+import static org.junit.Assert.*;
+
+import java.io.StringReader;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonException;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonPatchBuilder;
+import javax.json.JsonPointer;
+import javax.json.JsonReader;
+import javax.json.JsonString;
+import javax.json.JsonStructure;
+import javax.json.JsonValue;
+import javax.json.JsonValue.ValueType;
+import javax.json.spi.JsonProvider;
+
+import org.junit.Test;
+
+public class JsonPatchTest {
+	
+	@Test
+	public void testPatch() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/nested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+        JsonPatchBuilder jpb = new JsonPatchBuilder();
+        jpb.add("/s", JsonValue.NULL);
+        jpb.add("/y", 5);
+        jpb.add("/u", "c");
+        jpb.test("/s", JsonValue.NULL);
+        //jpb.add("/m", "{\"a\":10, \"b\":11}");
+        jpb.add("/qq", Json.createReader(new StringReader("{\"a\":10, \"b\":11}")).read());
+        jpb.copy("/x", "/qq/b");
+        //jpb.test("/x", 11);
+        jpb.remove("/qq/a");
+        jpb.move("/u", "/qq/b");
+        //jpb.remove("/m/a");
+        //jpb.move("/u", "/m/a");
+        JsonObject result = jpb.apply(obj);
+        System.out.println(obj);
+        System.out.println(result);
+        //assertEquals(obj, result);
+	}
+	
+	
+}
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java
index 21a5063..f1c4057 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonPointerTest.java
@@ -3,6 +3,7 @@
 import static org.junit.Assert.*;
 
 import javax.json.Json;
+import javax.json.JsonArray;
 import javax.json.JsonException;
 import javax.json.JsonNumber;
 import javax.json.JsonObject;
@@ -81,15 +82,152 @@
 		new JsonPointer("/a/c/g/");
 	}
 	
-	//@Test
-	public void testaddJsonPointer1() {
+	@Test
+	public void testaddJsonPointerPairToRoot() {
 		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/nested.json"));
         assertNotNull(loadInMemReader);
         JsonObject obj = loadInMemReader.readObject();
-		JsonObject result = new JsonPointer("/c/new").add(obj, Json.createValue("newval"));
-		System.out.println("res "+result);
-		JsonValue newVal = new JsonPointer("/c/new").getValue(result);
+		JsonObject result = new JsonPointer("/new").add(obj, Json.createValue("newval"));
+		JsonValue newVal = new JsonPointer("/new").getValue(result);
         assertNotNull(newVal);
 		assertEquals("newval", ((JsonString) newVal).getString());
+		assertEquals(3, result.size());
+	}
+	
+	@Test
+	public void testaddJsonPointerArrayToRoot() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/nested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/new").add(obj, Json.createArrayBuilder().add(true).build());
+		System.out.println(result);
+		JsonValue newVal = new JsonPointer("/new").getValue(result);
+        assertNotNull(newVal);
+		assertEquals("[true]", newVal.toString());
+		assertEquals(3, result.size());
+	}
+	
+	@Test
+	public void testaddJsonPointerPairToNested() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/c/d/2/e/r/2/new").add(obj, Json.createValue("newval"));
+		System.out.println(result);
+		JsonValue newVal = new JsonPointer("/c/d/2/e/r/2/new").getValue(result);
+        assertNotNull(newVal);
+		assertEquals("newval", ((JsonString) newVal).getString());
+		assertEquals(2, result.size());
+	}
+	
+	@Test(expected=JsonException.class)
+	public void testaddJsonPointerDoubleNonExist() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/x/y").add(obj, Json.createValue("newval"));
+		System.out.println(result);
+	}
+	
+	@Test
+	public void testaddJsonPointerPairToArrayNested() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/c/d/2/e/r/3").add(obj, Json.createValue("newval"));
+		JsonValue newVal = new JsonPointer("/c/d/2/e/r/3").getValue(result);
+        assertNotNull(newVal);
+		assertEquals("newval", ((JsonString) newVal).getString());
+		assertEquals(2, result.size());
+	}
+	
+	@Test
+	public void testaddJsonPointerPairToObjectNestedDash() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/c/d/2/e/-").add(obj, Json.createValue("newval"));
+		System.out.println(result);
+		JsonValue newVal = new JsonPointer("/c/d/2/e/-").getValue(result);
+        assertNotNull(newVal);
+		assertEquals("newval", ((JsonString) newVal).getString());
+		assertEquals(2, result.size());
+	}
+	
+	@Test
+	public void testaddJsonPointerPairToArrayNestedDash() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/c/d/2/e/r/-").add(obj, Json.createValue("newval"));
+		System.out.println(result);
+		JsonValue newVal = new JsonPointer("/c/d/2/e/r/3").getValue(result);
+        assertNotNull(newVal);
+		assertEquals("newval", ((JsonString) newVal).getString());
+		assertEquals(2, result.size());
+	}
+	
+	@Test
+	public void testaddJsonPointerSet() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/c/d/2/e").add(obj, Json.createValue("newval"));
+		JsonValue newVal = new JsonPointer("/c/d/2/e").getValue(result);
+        assertNotNull(newVal);
+		assertEquals("newval", ((JsonString) newVal).getString());
+		assertEquals(2, result.size());
+	}
+	
+	@Test
+	public void testaddJsonPointerPairToArrayNestedReplace() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/c/d/2/e/0").add(obj, Json.createValue("newval"));
+		JsonValue newVal = new JsonPointer("/c/d/2/e/0").getValue(result);
+        assertNotNull(newVal);
+		assertEquals("newval", ((JsonString) newVal).getString());
+		assertEquals(2, result.size());
+	}
+	
+	@Test
+	public void testReplace() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("/c/d/2/e").replace(obj, Json.createValue("newval"));
+		JsonValue newVal = new JsonPointer("/c/d/2/e").getValue(result);
+        assertNotNull(newVal);
+		assertEquals("newval", ((JsonString) newVal).getString());
+		assertEquals(2, result.size());
+	}
+	
+	@Test
+	public void testRemove() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+        System.out.println(obj);
+        JsonValue newVal = new JsonPointer("/c/d/2").getValue(obj);
+        assertNotNull(newVal);
+		assertEquals(2, ((JsonObject) newVal).size());
+        
+		JsonObject result = new JsonPointer("/c/d/2/e").remove(obj);
+		System.out.println(result);
+		newVal = new JsonPointer("/c/d/2").getValue(result);
+        assertNotNull(newVal);
+		assertEquals(1, ((JsonObject) newVal).size());
+		assertEquals(2, result.size());
+	}
+	
+	@Test
+	public void testRemoveAll() {
+		final JsonReader loadInMemReader = Json.createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/deepnested.json"));
+        assertNotNull(loadInMemReader);
+        JsonObject obj = loadInMemReader.readObject();
+		JsonObject result = new JsonPointer("").remove(obj);
+		System.out.println(result);
+		assertEquals(JsonValue.EMPTY_JSON_OBJECT, result);
 	}
 }
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 644a91b..4067e15 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
@@ -27,6 +27,8 @@
 import java.io.ByteArrayInputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
 import java.nio.charset.Charset;
 import java.util.Collections;
 import java.util.HashMap;
@@ -37,6 +39,8 @@
 import javax.json.JsonObject;
 import javax.json.JsonReader;
 import javax.json.JsonStructure;
+import javax.json.JsonValue;
+import javax.json.stream.JsonParsingException;
 
 import org.junit.Test;
 
@@ -413,6 +417,22 @@
         assertEquals(0, object.size());
         reader.close();
     }
+    
+    @Test
+    public void bug() {
+        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
+            {
+                put("org.apache.johnzon.default-char-buffer", "1");
+            }
+        }).createReader(new StringReader("[1, \"\", \"aaaaaaa\", \"\", \"aaaaaaa\", \"\", 100]"));
+        assertNotNull(reader);
+        final JsonArray ar = reader.readArray();
+        assertNotNull(ar);
+        assertEquals(100, ar.getInt(6));
+        reader.close();
+    }
+    
+    
 
     @Test
     public void emptyArrayOneCharBufferSize() {
@@ -464,4 +484,49 @@
         assertEquals("fdmcd", object.getJsonObject("//object").getString("sub"));
         reader.close();
     }
+    
+    @Test
+    public void singleTrueValue() {
+    	assertEquals(JsonValue.TRUE, Json.createReader(new StringReader("true")).readValue());
+    }
+    
+    @Test
+    public void singleFalseValue() {
+    	assertEquals(JsonValue.FALSE, Json.createReader(new StringReader("false")).readValue());
+    }
+    
+    @Test
+    public void singleNullValue() {
+    	assertEquals(JsonValue.NULL, Json.createReader(new StringReader("null")).readValue());
+    }
+    
+    @Test(expected=JsonParsingException.class)
+    public void singleBadValue() {
+    	assertEquals(JsonValue.NULL, Json.createReader(new StringReader("nullll")).readValue());
+    }
+    
+    @Test
+    public void singleStringValue() {
+    	assertEquals(Json.createValue("astring"), Json.createReader(new StringReader("\"astring\"")).readValue());
+    }
+    
+    @Test
+    public void singleNumberValue() {
+    	assertEquals(Json.createValue(1), Json.createReader(new StringReader("1")).readValue());
+    }
+    
+    @Test
+    public void singleENumberValue() {
+    	assertEquals(Json.createValue(new BigDecimal("-4.9e-4")), Json.createReader(new StringReader("-4.9e-4")).readValue());
+    }
+    
+    @Test
+    public void singleENumberValueA() {
+    	assertEquals(Json.createArrayBuilder().add(new BigDecimal("-4.9e-4")).build(), Json.createReader(new StringReader("[-4.9e-4]")).readArray());
+    }
+    
+    @Test(expected=JsonParsingException.class)
+    public void singleNumberAsStructure() {
+    	Json.createReader(new StringReader("112")).read();
+    }
 }
\ No newline at end of file
diff --git a/johnzon-core/src/test/resources/json/deepnested.json b/johnzon-core/src/test/resources/json/deepnested.json
new file mode 100644
index 0000000..24fc570
--- /dev/null
+++ b/johnzon-core/src/test/resources/json/deepnested.json
@@ -0,0 +1,22 @@
+{
+   "a":"b",
+   "c":{
+      "l":"m",
+      "d":[
+         1,
+         2,
+         {
+            "x":"y",
+            "e":{
+               "r":[
+                  7,
+                  8,
+                  {
+                     "z":"b"
+                  }
+               ]
+            }
+         }
+      ]
+   }
+}
\ No newline at end of file