Improve generator performance
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/HStack.java b/johnzon-core/src/main/java/org/apache/johnzon/core/HStack.java
deleted file mode 100644
index eafbe0e..0000000
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/HStack.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.johnzon.core;
-
-import java.io.Serializable;
-
-public class HStack<T> implements Serializable{
-
-    private Node<T> topElement = null;
-    private int size;
-    
-    
-    private static final class Node<T> implements Serializable{
-        final Node<T> previous;
-        final T object;
-
-        private Node(final Node<T> previous, final T object) {
-            super();
-            this.previous = previous;
-            this.object = object;
-        }
-    }
-    
-    
-    void push(T object) {
-        topElement = new Node<T>(topElement, object);
-        size++;
-    }
-    
-    T pop() {
-        
-        if(topElement == null) return null;
-        
-        T tmp = topElement.object;
-        topElement = topElement.previous;
-        size--;
-        return tmp;
-    }
-    
-    T peek() {
-        return topElement == null?null:topElement.object;
-    }
-    
-    int size() {
-        return size;
-    }
-    
-}
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java
index 92abbcd..7c021a8 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorFactoryImpl.java
@@ -31,45 +31,44 @@
 import javax.json.stream.JsonGenerator;
 import javax.json.stream.JsonGeneratorFactory;
 
-public class JsonGeneratorFactoryImpl extends AbstractJsonFactory implements JsonGeneratorFactory {    
+public class JsonGeneratorFactoryImpl extends AbstractJsonFactory implements JsonGeneratorFactory {
     public static final String GENERATOR_BUFFER_LENGTH = "org.apache.johnzon.default-char-buffer-generator";
-    public static final int DEFAULT_GENERATOR_BUFFER_LENGTH =  Integer.getInteger(GENERATOR_BUFFER_LENGTH, 64 * 1024); //64k
-   
-    static final Collection<String> SUPPORTED_CONFIG_KEYS = asList(
-        JsonGenerator.PRETTY_PRINTING, GENERATOR_BUFFER_LENGTH, BUFFER_STRATEGY
-    );
+    public static final int DEFAULT_GENERATOR_BUFFER_LENGTH = Integer.getInteger(GENERATOR_BUFFER_LENGTH, 64 * 1024); //64k
+
+    static final Collection<String> SUPPORTED_CONFIG_KEYS = asList(JsonGenerator.PRETTY_PRINTING, GENERATOR_BUFFER_LENGTH, BUFFER_STRATEGY);
     //key caching currently disabled
     private final ConcurrentMap<String, String> cache = null;//new ConcurrentHashMap<String, String>();
     private final boolean pretty;
     private final BufferStrategy.BufferProvider<char[]> bufferProvider;
 
     public JsonGeneratorFactoryImpl(final Map<String, ?> config) {
-        
-          super(config, SUPPORTED_CONFIG_KEYS, null); 
-          
-          this.pretty = getBool(JsonGenerator.PRETTY_PRINTING, false);
-          
-          final int bufferSize = getInt(GENERATOR_BUFFER_LENGTH, DEFAULT_GENERATOR_BUFFER_LENGTH);
-          if (bufferSize <= 0) {
-              throw new IllegalArgumentException("buffer length must be greater than zero");
-          }
 
-          this.bufferProvider = getBufferProvider().newCharProvider(bufferSize);
+        super(config, SUPPORTED_CONFIG_KEYS, null);
+
+        this.pretty = getBool(JsonGenerator.PRETTY_PRINTING, false);
+
+        final int bufferSize = getInt(GENERATOR_BUFFER_LENGTH, DEFAULT_GENERATOR_BUFFER_LENGTH);
+        if (bufferSize <= 0) {
+            throw new IllegalArgumentException("buffer length must be greater than zero");
+        }
+
+        this.bufferProvider = getBufferProvider().newCharProvider(bufferSize);
     }
 
     @Override
     public JsonGenerator createGenerator(final Writer writer) {
-        return new JsonGeneratorImpl(writer, bufferProvider, cache, pretty);
+        return pretty ? new JsonPrettyGeneratorImpl(writer, bufferProvider, cache) : new JsonGeneratorImpl(writer, bufferProvider, cache);
     }
 
     @Override
     public JsonGenerator createGenerator(final OutputStream out) {
-        return new JsonGeneratorImpl(out, bufferProvider, cache, pretty);
+        return pretty ? new JsonPrettyGeneratorImpl(out, bufferProvider, cache) : new JsonGeneratorImpl(out, bufferProvider, cache);
     }
 
     @Override
     public JsonGenerator createGenerator(final OutputStream out, final Charset charset) {
-        return new JsonGeneratorImpl(out,charset, bufferProvider, cache, pretty);
+        return pretty ? new JsonPrettyGeneratorImpl(out, charset, bufferProvider, cache) : new JsonGeneratorImpl(out, charset,
+                bufferProvider, cache);
     }
 
     @Override
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java
index d6a789e..173607e 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonGeneratorImpl.java
@@ -26,6 +26,7 @@
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.nio.charset.Charset;
+import java.util.ArrayDeque;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.ConcurrentMap;
@@ -46,12 +47,9 @@
     private final BufferStrategy.BufferProvider<char[]> bufferProvider;
     private final char[] buffer;
     private int bufferPos = 0;
-    private final boolean prettyPrint;
-    private static final String INDENT = "  ";
     //private final ConcurrentMap<String, String> cache;
-    private int depth = 0;
 
-    private final HStack<GeneratorState> state = new HStack<GeneratorState>();
+    private final ArrayDeque<GeneratorState> state = new ArrayDeque<JsonGeneratorImpl.GeneratorState>(100);
 
     private enum GeneratorState {
         INITIAL(false, true), START_OBJECT(true, false), IN_OBJECT(true, false), AFTER_KEY(false, true), START_ARRAY(false, true), IN_ARRAY(
@@ -67,37 +65,38 @@
     }
 
     JsonGeneratorImpl(final Writer writer, final BufferStrategy.BufferProvider<char[]> bufferProvider,
-            final ConcurrentMap<String, String> cache, final boolean prettyPrint) {
+            final ConcurrentMap<String, String> cache) {
         this.writer = writer;
         //this.cache = cache;
         this.buffer = bufferProvider.newBuffer();
         this.bufferProvider = bufferProvider;
-        this.prettyPrint = prettyPrint;
         state.push(GeneratorState.INITIAL);
     }
 
     JsonGeneratorImpl(final OutputStream out, final BufferStrategy.BufferProvider<char[]> bufferProvider,
-            final ConcurrentMap<String, String> cache, final boolean prettyPrint) {
-        this(new OutputStreamWriter(out, UTF8_CHARSET), bufferProvider, cache, prettyPrint);
+            final ConcurrentMap<String, String> cache) {
+        this(new OutputStreamWriter(out, UTF8_CHARSET), bufferProvider, cache);
     }
 
     JsonGeneratorImpl(final OutputStream out, final Charset encoding, final BufferStrategy.BufferProvider<char[]> bufferProvider,
-            final ConcurrentMap<String, String> cache, final boolean prettyPrint) {
-        this(new OutputStreamWriter(out, encoding), bufferProvider, cache, prettyPrint);
+            final ConcurrentMap<String, String> cache) {
+        this(new OutputStreamWriter(out, encoding), bufferProvider, cache);
     }
 
-    private void writeEol() {
-        if (prettyPrint) {
-            justWrite(EOL);
-        }
+    protected void incrementDepth() {
+
     }
 
-    private void writeIndent() {
-        if (prettyPrint && depth > 0) {
-            for (int i = 0; i < depth; i++) {
-                justWrite(INDENT);
-            }
-        }
+    protected void decrementDepth() {
+
+    }
+
+    protected void writeEol() {
+
+    }
+
+    protected void writeIndent() {
+
     }
 
     //caching currently disabled
@@ -135,7 +134,7 @@
         state.push(GeneratorState.START_OBJECT);
 
         writeIndent();
-        depth++;
+        incrementDepth();
         justWrite(START_OBJECT_CHAR);
 
         writeEol();
@@ -149,7 +148,7 @@
         justWrite(START_OBJECT_CHAR);
         writeEol();
         state.push(GeneratorState.START_OBJECT);
-        depth++;
+        incrementDepth();
         return this;
     }
 
@@ -157,7 +156,7 @@
     public JsonGenerator writeStartArray() {
         prepareValue();
         state.push(GeneratorState.START_ARRAY);
-        depth++;
+        incrementDepth();
         writeIndent();
         justWrite(START_ARRAY_CHAR);
         writeEol();
@@ -171,7 +170,7 @@
         justWrite(START_ARRAY_CHAR);
         writeEol();
         state.push(GeneratorState.START_ARRAY);
-        depth++;
+        incrementDepth();
         return this;
     }
 
@@ -204,12 +203,12 @@
                 write(name, JsonString.class.cast(value).getString());
                 break;
             case NUMBER:
-                //TODO optimize
-                final JsonNumber number = JsonNumber.class.cast(value);
-                if (number.isIntegral()) {
-                    write(name, number.longValueExact());
+                if (value instanceof JsonDoubleImpl) {
+                    write(name, JsonDoubleImpl.class.cast(value).doubleValue());
+                } else if (value instanceof JsonLongImpl) {
+                    write(name, JsonLongImpl.class.cast(value).longValue());
                 } else {
-                    write(name, number.bigDecimalValue());
+                    write(name, JsonNumber.class.cast(value).bigDecimalValue());
                 }
                 break;
             case TRUE:
@@ -255,12 +254,12 @@
                 write(JsonString.class.cast(value).getString());
                 break;
             case NUMBER:
-                //TODO optimize
-                final JsonNumber number = JsonNumber.class.cast(value);
-                if (number.isIntegral()) {
-                    write(number.longValueExact());
+                if (value instanceof JsonDoubleImpl) {
+                    write(JsonDoubleImpl.class.cast(value).doubleValue());
+                } else if (value instanceof JsonLongImpl) {
+                    write(JsonLongImpl.class.cast(value).longValue());
                 } else {
-                    write(number.bigDecimalValue());
+                    write(JsonNumber.class.cast(value).bigDecimalValue());
                 }
                 break;
             case TRUE:
@@ -353,7 +352,7 @@
     public JsonGenerator writeEnd() {
         checkArrayOrObject(false);
         final GeneratorState last = state.pop();
-        depth--;
+        decrementDepth();
         writeEol();
         writeIndent();
         if (last == GeneratorState.IN_ARRAY || last == GeneratorState.START_ARRAY) {
@@ -467,6 +466,15 @@
         }
     }
 
+    private final static char[][] REPLACEMENT_CHARS;
+
+    static {
+        REPLACEMENT_CHARS = new char[32][];
+        for (int i = 0; i < 32; i++) {
+            REPLACEMENT_CHARS[i] = toUnicode((char) i).toCharArray();
+        }
+    }
+
     private void writeEscaped0(final String value) {
         int len = 0;
         if (value == null || (len = value.length()) == 0) {
@@ -475,13 +483,11 @@
 
         for (int i = 0; i < len; i++) {
             char c = value.charAt(i);
-
+            final int y = i;
             while (c != ESCAPE_CHAR && c != QUOTE_CHAR && c >= SPACE) {
 
-                //read fast
-                justWrite(c);
-
                 if (i >= len - 1) {
+                    justWrite(value, y, i - y + 1);
                     return;
                 }
 
@@ -489,6 +495,8 @@
                 c = value.charAt(i);
             }
 
+            justWrite(value, y, i - y);
+
             switch (c) {
                 case QUOTE_CHAR:
                 case ESCAPE_CHAR:
@@ -496,30 +504,29 @@
                     justWrite(c);
                     break;
                 default:
-                    if (c < SPACE) {
-                        switch (c) {
-                            case EOL:
-                                justWrite("\\n");
-                                break;
-                            case '\r':
-                                justWrite("\\r");
-                                break;
-                            case '\t':
-                                justWrite("\\t");
-                                break;
-                            case '\b':
-                                justWrite("\\b");
-                                break;
-                            case '\f':
-                                justWrite("\\f");
-                                break;
-                            default:
-                                justWrite(toUnicode(c));
-                        }
-                    } else if ((c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
-                        justWrite(toUnicode(c));
-                    } else {
-                        justWrite(c);
+                    switch (c) {
+                        case EOL:
+                            justWrite('\\');
+                            justWrite('n');
+                            break;
+                        case '\r':
+                            justWrite('\\');
+                            justWrite('r');
+                            break;
+                        case '\t':
+                            justWrite('\\');
+                            justWrite('t');
+                            break;
+                        case '\b':
+                            justWrite('\\');
+                            justWrite('b');
+                            break;
+                        case '\f':
+                            justWrite('\\');
+                            justWrite('f');
+                            break;
+                        default:
+                            justWrite(REPLACEMENT_CHARS[c]);
                     }
             }
         }
@@ -534,17 +541,24 @@
         return s;
     }
 
-    private void justWrite(final String value) {
-        final int valueLength = value.length();
+    protected void justWrite(final String value) {
+        justWrite(value, 0, value.length());
+    }
+
+    protected void justWrite(final String value, final int offset, final int valueLength) {
+
+        if (valueLength == 0) {
+            return;
+        }
 
         if (bufferPos + valueLength >= buffer.length) {
 
-            int start = 0;
+            int start = offset;
             int len = buffer.length - bufferPos;
 
             while (true) {
                 int end = start + len;
-                if (end > valueLength) {
+                if (end > valueLength + offset) {
                     end = valueLength;
                 }
 
@@ -564,12 +578,56 @@
             }
         } else {
             //fits completely into the buffer
-            value.getChars(0, valueLength, buffer, bufferPos);
+            value.getChars(offset, valueLength + offset, buffer, bufferPos);
             bufferPos += valueLength;
         }
     }
 
-    private void justWrite(final char value) {
+    protected void justWrite(final char[] value) {
+        justWrite(value, 0, value.length);
+    }
+
+    protected void justWrite(final char[] value, final int offset, final int valueLength) {
+
+        if (valueLength == 0) {
+            return;
+        }
+
+        if (bufferPos + valueLength >= buffer.length) {
+
+            int start = offset;
+            int len = buffer.length - bufferPos;
+
+            while (true) {
+                int end = start + len;
+                if (end > valueLength + offset) {
+                    end = valueLength;
+                }
+
+                //value.getChars(start, end, buffer, bufferPos);
+                System.arraycopy(value, start, buffer, bufferPos, end - start);
+
+                bufferPos += (end - start);
+                start += (len);
+
+                if (start >= valueLength) {
+                    return;
+                }
+
+                if (bufferPos >= buffer.length) {
+                    flushBuffer();
+                    len = buffer.length;
+                }
+            }
+        } else {
+            //fits completely into the buffer
+            //value.getChars(offset, valueLength + offset, buffer, bufferPos);
+            System.arraycopy(value, offset, buffer, bufferPos, valueLength);
+            bufferPos += valueLength;
+        }
+    }
+
+    protected void justWrite(final char value) {
         if (bufferPos >= buffer.length) {
             flushBuffer();
         }
@@ -675,131 +733,19 @@
 
     private void writeValue(final String value) {
         prepareValue();
-        justWrite(String.valueOf(value));
+        justWrite(value);
         alignState();
     }
 
     private void writeValue(final int value) {
         prepareValue();
-        writeInt0(value);
+        justWrite(String.valueOf(value));
         alignState();
     }
 
     private void writeValue(final long value) {
         prepareValue();
-        writeLong0(value);
+        justWrite(String.valueOf(value));
         alignState();
     }
-
-    //unoptimized, see below
-    private void writeLong0(final long i) {
-        justWrite(String.valueOf(i));
-    }
-
-    //unoptimized, see below
-    private void writeInt0(final int i) {
-        justWrite(String.valueOf(i));
-    }
-
-    //optimized number optimizations
-    /*
-        private void writeLong0(final long i) {
-            if (i == Long.MIN_VALUE) {
-                justWrite("-9223372036854775808");
-                return;
-            }
-            final int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
-            final char[] buf = new char[size];
-            getChars(i, size, buf);
-            justWrite(buf);
-        }
-
-        private void writeInt0(final int i) {
-            if (i == Integer.MIN_VALUE) {
-                justWrite("-2147483648");
-                return;
-            }
-            final int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
-            final char[] buf = new char[size];
-            getChars(i, size, buf);
-            justWrite(buf);
-        }
-
-        private final static char[] DIGIT_TENS = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1',
-                '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4',
-                '4', '4', '4', '4', '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '6', '6', '6', '6', '6', '6', '6', '6',
-                '6', '6', '7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8', '8', '8', '8', '8', '8', '8', '9', '9', '9',
-                '9', '9', '9', '9', '9', '9', '9', };
-
-        private final static char[] DIGIT_ONES = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7',
-                '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2',
-                '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7',
-                '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2',
-                '3', '4', '5', '6', '7', '8', '9', };
-
-        private final static char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
-                'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };
-
-        // Requires positive x
-        private static int stringSize(final long x) {
-            long p = 10;
-            for (int i = 1; i < 19; i++) {
-                if (x < p) {
-                    return i;
-                }
-                p = 10 * p;
-            }
-            return 19;
-        }
-
-        private static void getChars(long i, final int index, final char[] buf) {
-            long q;
-            int r;
-            int charPos = index;
-            char sign = 0;
-
-            if (i < 0) {
-                sign = '-';
-                i = -i;
-            }
-
-            // Get 2 digits/iteration using longs until quotient fits into an int
-            while (i > Integer.MAX_VALUE) {
-                q = i / 100;
-                // really: r = i - (q * 100);
-                r = (int) (i - ((q << 6) + (q << 5) + (q << 2)));
-                i = q;
-                buf[--charPos] = DIGIT_ONES[r];
-                buf[--charPos] = DIGIT_TENS[r];
-            }
-
-            // Get 2 digits/iteration using ints
-            int q2;
-            int i2 = (int) i;
-            while (i2 >= 65536) {
-                q2 = i2 / 100;
-                // really: r = i2 - (q * 100);
-                r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
-                i2 = q2;
-                buf[--charPos] = DIGIT_ONES[r];
-                buf[--charPos] = DIGIT_TENS[r];
-            }
-
-            // Fall thru to fast mode for smaller numbers
-            // assert(i2 <= 65536, i2);
-            for (;;) {
-                q2 = (i2 * 52429) >>> (16 + 3);
-                r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ...
-                buf[--charPos] = DIGITS[r];
-                i2 = q2;
-                if (i2 == 0) {
-                    break;
-                }
-            }
-            if (sign != 0) {
-                buf[--charPos] = sign;
-            }
-        }
-     */
-
 }
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPrettyGeneratorImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPrettyGeneratorImpl.java
new file mode 100644
index 0000000..01c2dcd
--- /dev/null
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonPrettyGeneratorImpl.java
@@ -0,0 +1,69 @@
+/*
+ * 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.core;
+
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.johnzon.core.BufferStrategy.BufferProvider;
+
+class JsonPrettyGeneratorImpl extends JsonGeneratorImpl {
+
+    private static final String INDENT = "  ";
+    private int depth;
+
+    JsonPrettyGeneratorImpl(final OutputStream out, final BufferProvider<char[]> bufferProvider, final ConcurrentMap<String, String> cache) {
+        super(out, bufferProvider, cache);
+    }
+
+    JsonPrettyGeneratorImpl(final OutputStream out, final Charset encoding, final BufferProvider<char[]> bufferProvider,
+            final ConcurrentMap<String, String> cache) {
+        super(out, encoding, bufferProvider, cache);
+    }
+
+    JsonPrettyGeneratorImpl(final Writer writer, final BufferProvider<char[]> bufferProvider, final ConcurrentMap<String, String> cache) {
+        super(writer, bufferProvider, cache);
+    }
+
+    @Override
+    protected void incrementDepth() {
+        depth++;
+    }
+
+    @Override
+    protected void decrementDepth() {
+        depth--;
+    }
+
+    @Override
+    protected void writeEol() {
+        justWrite(EOL);
+    }
+
+    @Override
+    protected void writeIndent() {
+        if (depth > 0) {
+            for (int i = 0; i < depth; i++) {
+                justWrite(INDENT);
+            }
+        }
+    }
+}
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/HStackTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/HStackTest.java
deleted file mode 100644
index 24ded70..0000000
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/HStackTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.johnzon.core;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class HStackTest {
-
-    @Test
-    public void normalUse() {
-
-        final HStack<String> stack = new HStack<String>();
-        Assert.assertEquals(0, stack.size());
-        Assert.assertNull(stack.pop());
-        Assert.assertNull(stack.peek());
-
-        stack.push("1");
-        Assert.assertEquals(1, stack.size());
-        Assert.assertEquals("1", stack.peek());
-        Assert.assertEquals(1, stack.size());
-        Assert.assertEquals("1", stack.pop());
-        Assert.assertEquals(0, stack.size());
-
-        stack.push("1");
-        stack.push("2");
-        stack.push("3");
-        stack.push("4");
-        stack.push("5");
-        stack.push("6");
-        stack.push("7");
-
-        Assert.assertEquals(7, stack.size());
-        Assert.assertEquals("7", stack.peek());
-        Assert.assertEquals("7", stack.peek());
-        Assert.assertEquals("7", stack.peek());
-        Assert.assertEquals("7", stack.pop());
-        Assert.assertEquals("6", stack.pop());
-        Assert.assertEquals("5", stack.peek());
-        Assert.assertEquals(5, stack.size());
-        Assert.assertEquals("5", stack.pop());
-        Assert.assertEquals("4", stack.pop());
-        Assert.assertEquals("3", stack.pop());
-        Assert.assertEquals("2", stack.pop());
-        Assert.assertEquals("1", stack.pop());
-        Assert.assertNull(stack.peek());
-        Assert.assertNull(stack.peek());
-        Assert.assertNull(stack.peek());
-        Assert.assertNull(stack.pop());
-        Assert.assertNull(stack.pop());
-        Assert.assertEquals(0, stack.size());
-    }
-}
diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java
index e2f5202..1ff6d83 100644
--- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java
+++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonGeneratorImplTest.java
@@ -66,238 +66,216 @@
     }
     
     @Test
+    public void escapeZero() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().write("\0").write(String.valueOf((char) 29)).writeEnd().close();
+        assertEquals("[\"\\u0000\",\"\\u001d\"]", new String(baos.toByteArray()));
+    }
+
+    @Test
     public void stringArray() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         Json.createGenerator(baos).writeStartArray().write("val1").write("val2").writeEnd().close();
         assertEquals("[\"val1\",\"val2\"]", new String(baos.toByteArray()));
     }
-    
+
     @Test
     public void stringArrayEscapes() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         Json.createGenerator(baos).writeStartArray().write("\"val1\t\u0010").write("val2\\").writeEnd().close();
         assertEquals("[\"\\\"val1\\t\\u0010\",\"val2\\\\\"]", new String(baos.toByteArray()));
     }
-    
+
     @Test
     public void stringArrayEscapes2() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         Json.createGenerator(baos).writeStartArray().write("\"val1\t\u0067").write("val2\\").writeEnd().close();
         assertEquals("[\"\\\"val1\\tg\",\"val2\\\\\"]", new String(baos.toByteArray()));
     }
-    
+
     @Test
     public void emptyStringArray() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         Json.createGenerator(baos).writeStartArray().writeNull().write("").writeEnd().close();
         assertEquals("[null,\"\"]", new String(baos.toByteArray()));
     }
-    
+
+    @Test
+    public void wsStringArray() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().write(new JsonStringImpl(" ")).write(new JsonStringImpl("")).write("").write(" ")
+        .writeEnd().close();
+        assertEquals("[\" \",\"\",\"\",\" \"]", new String(baos.toByteArray()));
+    }
+
     @Test
     public void nullLiteralArray() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         Json.createGenerator(baos).writeStartArray().writeNull().write(JsonValue.NULL).writeEnd().close();
         assertEquals("[null,null]", new String(baos.toByteArray()));
     }
-    
+
     @Test
     public void boolLiteralArray() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         Json.createGenerator(baos).writeStartArray().write(JsonValue.FALSE).write(JsonValue.TRUE).writeEnd().close();
         assertEquals("[false,true]", new String(baos.toByteArray()));
     }
-    
-    @Test(expected=JsonGenerationException.class)
+
+    @Test(expected = JsonGenerationException.class)
     public void fail1() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeStartArray("test");      
+        Json.createGenerator(baos).writeStartArray("test");
     }
-    
-    @Test(expected=JsonGenerationException.class)
+
+    @Test(expected = JsonGenerationException.class)
     public void fail2() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .write("test",1);      
+        Json.createGenerator(baos).write("test", 1);
     }
-    
-    @Test(expected=JsonGenerationException.class)
+
+    @Test(expected = JsonGenerationException.class)
     public void fail3() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeStartObject()
-        .writeStartObject();
+        Json.createGenerator(baos).writeStartObject().writeStartObject();
     }
-    
-    @Test(expected=JsonGenerationException.class)
+
+    @Test(expected = JsonGenerationException.class)
     public void fail4() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeEnd();
+        Json.createGenerator(baos).writeEnd();
     }
-    
-    @Test(expected=JsonGenerationException.class)
+
+    @Test(expected = JsonGenerationException.class)
     public void fail5() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .close();
+        Json.createGenerator(baos).close();
     }
-    
-    @Test(expected=JsonGenerationException.class)
+
+    @Test(expected = JsonGenerationException.class)
     public void fail6() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeStartArray()
-        .writeStartObject("test");
+        Json.createGenerator(baos).writeStartArray().writeStartObject("test");
     }
-    
-    @Test(expected=JsonGenerationException.class)
+
+    @Test(expected = JsonGenerationException.class)
     public void fail7() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeStartArray()
-        .writeNull()
-        .writeStartObject()
-        .write("a", new BigDecimal("123.123"))
-        .write("b", true)
-        .write("c", new BigInteger("3312"))
-        .write("d", new JsonStringImpl("mystring"))
-        .writeEnd()
-        .close();
-        
+        Json.createGenerator(baos).writeStartArray().writeNull().writeStartObject().write("a", new BigDecimal("123.123")).write("b", true)
+                .write("c", new BigInteger("3312")).write("d", new JsonStringImpl("mystring")).writeEnd().close();
+
     }
-    
-    @Test(expected=JsonGenerationException.class)
+
+    @Test(expected = JsonGenerationException.class)
     public void fail9() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeStartObject()
-        .write("a", new BigDecimal("123.123"))
-        .write("b", true)
-        .write("c", new BigInteger("3312"))
-        .write("d", new JsonStringImpl("mystring"))
-        .writeEnd()
-        .writeStartObject()
-        .close();
-        
+        Json.createGenerator(baos).writeStartObject().write("a", new BigDecimal("123.123")).write("b", true)
+                .write("c", new BigInteger("3312")).write("d", new JsonStringImpl("mystring")).writeEnd().writeStartObject().close();
+
     }
-   
+
     @Test
     public void numbers() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeStartArray()
-        .writeNull()
-        .writeStartObject()
-        .write("a", new BigDecimal("123.123"))
-        .write("b", true)
-        .write("c", new BigInteger("3312"))
-        .write("d", new JsonStringImpl("Mystring"))
-        .writeEnd()
-        .writeEnd()
-        .close();
+        Json.createGenerator(baos).writeStartArray().writeNull().writeStartObject().write("a", new BigDecimal("123.123")).write("b", true)
+                .write("c", new BigInteger("3312")).write("d", new JsonStringImpl("Mystring")).writeEnd().writeEnd().close();
         assertEquals("[null,{\"a\":123.123,\"b\":true,\"c\":3312,\"d\":\"Mystring\"}]", new String(baos.toByteArray()));
     }
-    
+
+    @Test
+    public void integralNumbers() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().writeNull().writeStartObject().write("a", Long.MAX_VALUE).write("b", Long.MIN_VALUE)
+                .write("c", Integer.MAX_VALUE).write("d", Integer.MIN_VALUE).write("e", -198766172L).write("f", 188.001d).writeEnd()
+        .writeEnd().close();
+        assertEquals("[null,{\"a\":" + Long.MAX_VALUE + ",\"b\":" + Long.MIN_VALUE + ",\"c\":" + Integer.MAX_VALUE + ",\"d\":"
+                + Integer.MIN_VALUE + ",\"e\":-198766172,\"f\":188.001}]", new String(baos.toByteArray()));
+    }
+
+    @Test
+    public void integralNumbersSmall() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().writeNull().writeStartObject().write("a", 1).write("b", 1L).write("c", -6)
+                .write("d", -6L).write("e", 0).write("f", 0L).writeEnd().writeEnd().close();
+        assertEquals("[null,{\"a\":1,\"b\":1,\"c\":-6,\"d\":-6,\"e\":0,\"f\":0}]", new String(baos.toByteArray()));
+    }
+
+    @Test
+    public void integralNumbersSmall2() {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Json.createGenerator(baos).writeStartArray().writeNull().writeStartObject().write("a", 10).write("b", 10L).write("c", -10)
+                .write("d", -10L).write("e", 9).write("f", 9L).writeEnd().writeEnd().close();
+        assertEquals("[null,{\"a\":10,\"b\":10,\"c\":-10,\"d\":-10,\"e\":9,\"f\":9}]", new String(baos.toByteArray()));
+    }
+
     @Test
     public void numbers2() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeStartArray()
-        .writeNull()
-        .writeStartObject()
-        .write("a", 999999999L)
-        .write("b", 123)
-        .write("c", -444444444L)
-        .write("d",-123)
-        .writeEnd()
-        .writeEnd()
-        .close();
+        Json.createGenerator(baos).writeStartArray().writeNull().writeStartObject().write("a", 999999999L).write("b", 123)
+                .write("c", -444444444L).write("d", -123).writeEnd().writeEnd().close();
         assertEquals("[null,{\"a\":999999999,\"b\":123,\"c\":-444444444,\"d\":-123}]", new String(baos.toByteArray()));
     }
-    
+
     @Test
     public void arrayInArray() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        Json.createGenerator(baos)
-        .writeStartArray()
-        .writeStartArray()
-        .writeNull()
-        .writeEnd()
-        .writeEnd()
-        .close();
-         assertEquals("[[null]]", new String(baos.toByteArray()));
+        Json.createGenerator(baos).writeStartArray().writeStartArray().writeNull().writeEnd().writeEnd().close();
+        assertEquals("[[null]]", new String(baos.toByteArray()));
     }
-    
 
     @Test
     public void generate() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         final JsonGenerator generator = Json.createGenerator(baos);
 
-        generator.writeStartObject().write("firstName", "John").write("lastName", "Smith").write("age", 25)
-        .writeStartObject("address").write("streetAddress", "21 2nd Street").write("city", "New York")
-        .write("state", "NY").write("postalCode", "10021").writeEnd().writeStartArray("phoneNumber")
-        .writeStartObject().write("type", "home").write("number", "212 555-1234").writeEnd().writeStartObject()
-        .write("type", "fax").write("number", "646 555-4567").writeEnd().writeEnd().writeEnd().close();
+        generator.writeStartObject().write("firstName", "John").write("lastName", "Smith").write("age", 25).writeStartObject("address")
+                .write("streetAddress", "21 2nd Street").write("city", "New York").write("state", "NY").write("postalCode", "10021")
+                .writeEnd().writeStartArray("phoneNumber").writeStartObject().write("type", "home").write("number", "212 555-1234")
+                .writeEnd().writeStartObject().write("type", "fax").write("number", "646 555-4567").writeEnd().writeEnd().writeEnd()
+                .close();
 
         assertEquals("{\"firstName\":\"John\",\"lastName\":\"Smith\",\"age\":25,\"address\":"
                 + "{\"streetAddress\":\"21 2nd Street\",\"city\":\"New York\",\"state\":\"NY\",\"postalCode\":\"10021\"},"
-                + "\"phoneNumber\":[{\"type\":\"home\",\"number\":\"212 555-1234\"},{\"type\":\"fax\",\"number\":\"646 555-4567\"}]}", 
+                + "\"phoneNumber\":[{\"type\":\"home\",\"number\":\"212 555-1234\"},{\"type\":\"fax\",\"number\":\"646 555-4567\"}]}",
                 new String(baos.toByteArray()));
     }
 
     @Test
     public void pretty() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        final JsonGenerator generator = Json.createGeneratorFactory(new HashMap<String, Object>() {{
-            put(JsonGenerator.PRETTY_PRINTING, true);
-        }}).createGenerator(baos);
+        final JsonGenerator generator = Json.createGeneratorFactory(new HashMap<String, Object>() {
+            {
+                put(JsonGenerator.PRETTY_PRINTING, true);
+            }
+        }).createGenerator(baos);
 
-        generator.writeStartObject().write("firstName", "John").write("lastName", "Smith")
-        .write("age", 25).writeStartObject("address").write("streetAddress", "21 2nd Street")
-        .write("city", "New York").write("state", "NY").write("postalCode", "10021").writeEnd()
-        .writeStartArray("phoneNumber").writeStartObject().write("type", "home").write("number", "212 555-1234")
-        .writeEnd().writeStartObject().write("type", "fax").write("number", "646 555-4567").writeEnd().writeEnd()
-        .writeEnd().close();
+        generator.writeStartObject().write("firstName", "John").write("lastName", "Smith").write("age", 25).writeStartObject("address")
+                .write("streetAddress", "21 2nd Street").write("city", "New York").write("state", "NY").write("postalCode", "10021")
+                .writeEnd().writeStartArray("phoneNumber").writeStartObject().write("type", "home").write("number", "212 555-1234")
+                .writeEnd().writeStartObject().write("type", "fax").write("number", "646 555-4567").writeEnd().writeEnd().writeEnd()
+                .close();
 
-        assertEquals("{\n" +
-                        "  \"firstName\":\"John\",\n" +
-                        "  \"lastName\":\"Smith\",\n" +
-                        "  \"age\":25,\n" +
-                        "  \"address\":{\n" +
-                        "    \"streetAddress\":\"21 2nd Street\",\n" +
-                        "    \"city\":\"New York\",\n" +
-                        "    \"state\":\"NY\",\n" +
-                        "    \"postalCode\":\"10021\"\n" +
-                        "  },\n" +
-                        "  \"phoneNumber\":[\n" +
-                        "    {\n" +
-                        "      \"type\":\"home\",\n" +
-                        "      \"number\":\"212 555-1234\"\n" +
-                        "    },\n" +
-                        "    {\n" +
-                        "      \"type\":\"fax\",\n" +
-                        "      \"number\":\"646 555-4567\"\n" +
-                        "    }\n" +
-                        "  ]\n" +
-                        "}", new String(baos.toByteArray()));
+        assertEquals("{\n" + "  \"firstName\":\"John\",\n" + "  \"lastName\":\"Smith\",\n" + "  \"age\":25,\n" + "  \"address\":{\n"
+                + "    \"streetAddress\":\"21 2nd Street\",\n" + "    \"city\":\"New York\",\n" + "    \"state\":\"NY\",\n"
+                + "    \"postalCode\":\"10021\"\n" + "  },\n" + "  \"phoneNumber\":[\n" + "    {\n" + "      \"type\":\"home\",\n"
+                + "      \"number\":\"212 555-1234\"\n" + "    },\n" + "    {\n" + "      \"type\":\"fax\",\n"
+                + "      \"number\":\"646 555-4567\"\n" + "    }\n" + "  ]\n" + "}", new String(baos.toByteArray()));
     }
-    
+
     @Test
     public void prettySimple() {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        final JsonGenerator generator = Json.createGeneratorFactory(new HashMap<String, Object>() {{
-            put(JsonGenerator.PRETTY_PRINTING, true);
-        }}).createGenerator(baos);
+        final JsonGenerator generator = Json.createGeneratorFactory(new HashMap<String, Object>() {
+            {
+                put(JsonGenerator.PRETTY_PRINTING, true);
+            }
+        }).createGenerator(baos);
 
         generator.writeStartObject().write("firstName", "John").writeEnd().close();
 
-        assertEquals("{\n" +
-                        "  \"firstName\":\"John\"\n" +
-                        "}", new String(baos.toByteArray()));
+        assertEquals("{\n" + "  \"firstName\":\"John\"\n" + "}", new String(baos.toByteArray()));
     }
-    
+
     @Test
     public void prettySimpleStructure() {
         final JsonWriterFactory writerFactory = Json.createWriterFactory(new HashMap<String, Object>() {
@@ -306,7 +284,7 @@
             }
         });
 
-        StringWriter buffer = new StringWriter();
+        final StringWriter buffer = new StringWriter();
 
         final JsonWriter writer = writerFactory.createWriter(buffer);
         writer.write(Json.createObjectBuilder().add("firstName", "John").build());
@@ -324,7 +302,7 @@
             }
         });
 
-        StringWriter buffer = new StringWriter();
+        final StringWriter buffer = new StringWriter();
 
         final JsonReader reader = Json.createReader(new ByteArrayInputStream("{\"firstName\":\"John\"}".getBytes()));
         final JsonWriter writer = writerFactory.createWriter(buffer);
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..54c1731 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
@@ -44,8 +44,6 @@
 
 public class JsonReaderImplTest {
 
-
-
     public JsonReaderImplTest() {
         if (!Charset.defaultCharset().equals(Charset.forName("UTF-8"))) {
             System.err.println("Default charset is " + Charset.defaultCharset() + ", must must be UTF-8");
@@ -170,11 +168,10 @@
         assertEquals("hallo\u20acö\uffff \u08a5 থ?ߧ$%&´'`*+#\udbff\udfff", object.getString("নa"));
         reader.close();
     }
-    
+
     @Test
     public void specialKeysWithStringAsByteArrayInputStream() {
         final String s = "{\"\\\"a\":\"\u0055\",\"\u0055\":\"test2\"}";
-        System.out.println(s);
         final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
                 new ByteArrayInputStream(s.getBytes(utf8Charset)), utf8Charset);
         assertNotNull(reader);
@@ -209,8 +206,7 @@
         assertTrue(Character.isLowSurrogate(charPair[1]));
         assertTrue(Character.isSurrogatePair(charPair[0], charPair[1]));
         final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
-                (new ByteArrayInputStream(("{\"\":\"Ö" + charPair[0] + charPair[1] + "\"}").getBytes(utf8Charset))),
-                utf8Charset);
+                (new ByteArrayInputStream(("{\"\":\"Ö" + charPair[0] + charPair[1] + "\"}").getBytes(utf8Charset))), utf8Charset);
         assertNotNull(reader);
         final JsonObject object = reader.readObject();
         assertNotNull(object);
@@ -254,8 +250,7 @@
     public void unicodeFailAscii() {
         final JsonReader reader = Json.createReaderFactory(getFactoryConfig()).createReader(
                 new ByteArrayInputStream(
-                        "{\"ন:4::,[{\udbff\udfff\":\"থii:üäöÖ.,;.-<>!§$%&()=?ß´'`*+#\udbff\udfff\"}".getBytes(asciiCharset)),
-                utf8Charset);
+                        "{\"ন:4::,[{\udbff\udfff\":\"থii:üäöÖ.,;.-<>!§$%&()=?ß´'`*+#\udbff\udfff\"}".getBytes(asciiCharset)), utf8Charset);
         assertNotNull(reader);
         final JsonObject object = reader.readObject();
         assertNotNull(object);
@@ -345,7 +340,7 @@
         assertEquals(-2, array.getInt(1));
         reader.close();
     }
-    
+
     @Test
     public void simple2BadBufferSize8() {
         final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
@@ -441,8 +436,7 @@
                 {
                     put("org.apache.johnzon.default-char-buffer", value);
                 }
-            }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/stringescape.json"),
-                    utf8Charset);
+            }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/stringescape.json"), utf8Charset);
             assertNotNull(reader);
             final JsonObject object = reader.readObject();
             assertNotNull(object);
@@ -454,9 +448,11 @@
 
     @Test
     public void comments() {
-        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {{
-            put("org.apache.johnzon.supports-comments", true);
-        }}).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/comments.json"));
+        final JsonReader reader = Json.createReaderFactory(new HashMap<String, Object>() {
+            {
+                put("org.apache.johnzon.supports-comments", true);
+            }
+        }).createReader(Thread.currentThread().getContextClassLoader().getResourceAsStream("json/comments.json"));
         final JsonObject object = reader.readObject();
         assertNotNull(object);
         assertEquals(3, object.size());
@@ -469,15 +465,15 @@
 
     @Test
     public void testGrowingString() throws Throwable {
-        JsonReaderFactory factory = Json.createReaderFactory(null);
-        StringBuilder sb = new StringBuilder();
+        final JsonReaderFactory factory = Json.createReaderFactory(null);
+        final StringBuilder sb = new StringBuilder();
         for (int i = 0; i < 40000; i++) {
             sb.append('x');
-            String growingString = sb.toString();
-            String str = "[4, \"\", \"" + growingString + "\", \"\", \"" + growingString + "\", \"\", 400]";
+            final String growingString = sb.toString();
+            final String str = "[4, \"\", \"" + growingString + "\", \"\", \"" + growingString + "\", \"\", 400]";
             try {
-                JsonReader reader = factory.createReader(new StringReader(str));
-                JsonArray array = reader.readArray();
+                final JsonReader reader = factory.createReader(new StringReader(str));
+                final JsonArray array = reader.readArray();
                 assertEquals(4, array.getInt(0));
                 assertEquals("", array.getString(1));
                 assertEquals(growingString, array.getString(2));
@@ -486,7 +482,7 @@
                 assertEquals("", array.getString(5));
                 assertEquals(400, array.getInt(6));
                 reader.close();
-            } catch (Throwable t) {
+            } catch (final Throwable t) {
                 throw new Throwable("Failed for growingString with length: " + i, t);
             }
         }
@@ -496,21 +492,21 @@
     public void testGrowingStringWithDifferentBufferSizes() throws Throwable {
         for (int size = 20; size < 500; size++) {
             final int k = size;
-            Map<String, Object> config = new HashMap<String, Object>() {
+            final Map<String, Object> config = new HashMap<String, Object>() {
                 {
                     put("org.apache.johnzon.default-char-buffer", k);
                 }
             };
-            JsonReaderFactory factory = Json.createReaderFactory(config);
+            final JsonReaderFactory factory = Json.createReaderFactory(config);
 
-            StringBuilder sb = new StringBuilder();
+            final StringBuilder sb = new StringBuilder();
             for (int i = 0; i < 1000; i++) {
                 sb.append('x');
-                String name = sb.toString();
-                String str = "[4, \"\", \"" + name + "\", \"\", \"" + name + "\", \"\", 400]";
+                final String name = sb.toString();
+                final String str = "[4, \"\", \"" + name + "\", \"\", \"" + name + "\", \"\", 400]";
                 try {
-                    JsonReader reader = factory.createReader(new StringReader(str));
-                    JsonArray array = reader.readArray();
+                    final JsonReader reader = factory.createReader(new StringReader(str));
+                    final JsonArray array = reader.readArray();
                     assertEquals(4, array.getInt(0));
                     assertEquals("", array.getString(1));
                     assertEquals(name, array.getString(2));
@@ -520,7 +516,7 @@
                     assertEquals(400, array.getInt(6));
                     reader.close();
 
-                } catch (Throwable t) {
+                } catch (final Throwable t) {
                     throw new Throwable("Failed for buffer size=" + size + " growingString with length: " + i, t);
                 }
             }