You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2019/01/29 10:30:19 UTC

[camel] branch master updated: Partially fixed the CS for camel-util-json

This is an automated email from the ASF dual-hosted git repository.

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new c9e786f  Partially fixed the CS for camel-util-json
c9e786f is described below

commit c9e786fce97b14b8b42ab67bc5ce1d77d8c41a9a
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Tue Jan 29 11:29:52 2019 +0100

    Partially fixed the CS for camel-util-json
---
 .../camel/util/json/DeserializationException.java  |   98 +-
 .../java/org/apache/camel/util/json/JsonArray.java |  744 ++++----
 .../org/apache/camel/util/json/JsonObject.java     | 1427 ++++++++-------
 .../java/org/apache/camel/util/json/Jsonable.java  |   45 +-
 .../java/org/apache/camel/util/json/Jsoner.java    | 1824 +++++++++++---------
 .../java/org/apache/camel/util/json/Yylex.java     | 1223 +++++++------
 .../java/org/apache/camel/util/json/Yytoken.java   |  121 +-
 7 files changed, 2995 insertions(+), 2487 deletions(-)

diff --git a/camel-util-json/src/main/java/org/apache/camel/util/json/DeserializationException.java b/camel-util-json/src/main/java/org/apache/camel/util/json/DeserializationException.java
index 596b4dd..483a634 100644
--- a/camel-util-json/src/main/java/org/apache/camel/util/json/DeserializationException.java
+++ b/camel-util-json/src/main/java/org/apache/camel/util/json/DeserializationException.java
@@ -1,79 +1,93 @@
-/* Copyright 2016 Clifton Labs
- * Licensed 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
+/**
+ * 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. */
+ * limitations under the License.
+ */
 package org.apache.camel.util.json;
 
-/** DeserializationException explains how and where the problem occurs in the source JSON text during deserialization.
- * @since 2.0.0 */
-public class DeserializationException extends Exception{
+/**
+ * DeserializationException explains how and where the problem occurs in the
+ * source JSON text during deserialization.
+ * 
+ * @since 2.0.0
+ */
+public class DeserializationException extends Exception {
     /** The kinds of exceptions that can trigger a DeserializationException. */
-    enum Problems{
-        @SuppressWarnings("javadoc")
-        DISALLOWED_TOKEN,
-        @SuppressWarnings("javadoc")
-        UNEXPECTED_CHARACTER,
-        @SuppressWarnings("javadoc")
-        UNEXPECTED_EXCEPTION,
+    enum Problems {
         @SuppressWarnings("javadoc")
+        DISALLOWED_TOKEN, @SuppressWarnings("javadoc")
+        UNEXPECTED_CHARACTER, @SuppressWarnings("javadoc")
+        UNEXPECTED_EXCEPTION, @SuppressWarnings("javadoc")
         UNEXPECTED_TOKEN;
     }
 
     private static final long serialVersionUID = -7880698968187728547L;
-    private final int         position;
-    private final Problems    problemType;
-    private final Object      unexpectedObject;
+    private final int position;
+    private final Problems problemType;
+    private final Object unexpectedObject;
 
-    /** @param position where the exception occurred.
+    /**
+     * @param position where the exception occurred.
      * @param problemType how the exception occurred.
-     * @param unexpectedObject what caused the exception. */
-    public DeserializationException(final int position, final Problems problemType, final Object unexpectedObject){
+     * @param unexpectedObject what caused the exception.
+     */
+    public DeserializationException(final int position, final Problems problemType, final Object unexpectedObject) {
         this.position = position;
         this.problemType = problemType;
         this.unexpectedObject = unexpectedObject;
     }
 
     @Override
-    public String getMessage(){
+    public String getMessage() {
         final StringBuilder sb = new StringBuilder();
-        switch(this.problemType){
-            case DISALLOWED_TOKEN:
-                sb.append("The disallowed token (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". If this is in error, try again with a parse that allows the token instead. Otherwise, fix the parsable string and try again.");
-                break;
-            case UNEXPECTED_CHARACTER:
-                sb.append("The unexpected character (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". Fix the parsable string and try again.");
-                break;
-            case UNEXPECTED_TOKEN:
-                sb.append("The unexpected token ").append(this.unexpectedObject).append(" was found at position ").append(this.position).append(". Fix the parsable string and try again.");
-                break;
-            case UNEXPECTED_EXCEPTION:
-                sb.append("Please report this to the library's maintainer. The unexpected exception that should be addressed before trying again occurred at position ").append(this.position).append(": ").append(this.unexpectedObject);
-                break;
-            default:
-                sb.append("Please report this to the library's maintainer. An error at position ").append(this.position).append(" occurred. There are no recovery recommendations available.");
-                break;
+        switch (this.problemType) {
+        case DISALLOWED_TOKEN:
+            sb.append("The disallowed token (").append(this.unexpectedObject).append(") was found at position ").append(this.position)
+                .append(". If this is in error, try again with a parse that allows the token instead. Otherwise, fix the parsable string and try again.");
+            break;
+        case UNEXPECTED_CHARACTER:
+            sb.append("The unexpected character (").append(this.unexpectedObject).append(") was found at position ").append(this.position)
+                .append(". Fix the parsable string and try again.");
+            break;
+        case UNEXPECTED_TOKEN:
+            sb.append("The unexpected token ").append(this.unexpectedObject).append(" was found at position ").append(this.position)
+                .append(". Fix the parsable string and try again.");
+            break;
+        case UNEXPECTED_EXCEPTION:
+            sb.append("Please report this to the library's maintainer. The unexpected exception that should be addressed before trying again occurred at position ")
+                .append(this.position).append(": ").append(this.unexpectedObject);
+            break;
+        default:
+            sb.append("Please report this to the library's maintainer. An error at position ").append(this.position)
+                .append(" occurred. There are no recovery recommendations available.");
+            break;
         }
         return sb.toString();
     }
 
     /** @return an index of the string character the error type occurred at. */
-    public int getPosition(){
+    public int getPosition() {
         return this.position;
     }
 
     /** @return the enumeration for how the exception occurred. */
-    public Problems getProblemType(){
+    public Problems getProblemType() {
         return this.problemType;
     }
 
     /** @return a representation of what caused the exception. */
-    public Object getUnexpectedObject(){
+    public Object getUnexpectedObject() {
         return this.unexpectedObject;
     }
 }
diff --git a/camel-util-json/src/main/java/org/apache/camel/util/json/JsonArray.java b/camel-util-json/src/main/java/org/apache/camel/util/json/JsonArray.java
index 8252808..dcc32e4 100644
--- a/camel-util-json/src/main/java/org/apache/camel/util/json/JsonArray.java
+++ b/camel-util-json/src/main/java/org/apache/camel/util/json/JsonArray.java
@@ -1,13 +1,19 @@
-/* Copyright 2016 Clifton Labs
- * Licensed 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
+/**
+ * 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. */
+ * limitations under the License.
+ */
 package org.apache.camel.util.json;
 
 import java.io.IOException;
@@ -19,328 +25,442 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 
-/** JsonArray is a common non-thread safe data format for a collection of data. The contents of a JsonArray are only
- * validated as JSON values on serialization.
+/**
+ * JsonArray is a common non-thread safe data format for a collection of data.
+ * The contents of a JsonArray are only validated as JSON values on
+ * serialization.
+ * 
  * @see Jsoner
- * @since 2.0.0 */
-public class JsonArray extends ArrayList<Object> implements Jsonable{
-	/** The serialization version this class is compatible
-	 * with. This value doesn't need to be incremented if and only if the only changes to occur were updating comments,
-	 * updating javadocs, adding new
-	 * fields to the class, changing the fields from static to non-static, or changing the fields from transient to non
-	 * transient. All other changes require this number be incremented. */
-	private static final long serialVersionUID = 1L;
+ * @since 2.0.0
+ */
+public class JsonArray extends ArrayList<Object> implements Jsonable {
+    /**
+     * The serialization version this class is compatible with. This value
+     * doesn't need to be incremented if and only if the only changes to occur
+     * were updating comments, updating javadocs, adding new fields to the
+     * class, changing the fields from static to non-static, or changing the
+     * fields from transient to non transient. All other changes require this
+     * number be incremented.
+     */
+    private static final long serialVersionUID = 1L;
 
-	/** Instantiates an empty JsonArray. */
-	public JsonArray(){
-		super();
-	}
+    /** Instantiates an empty JsonArray. */
+    public JsonArray() {
+        super();
+    }
 
-	/** Instantiate a new JsonArray using ArrayList's constructor of the same type.
-	 * @param collection represents the elements to produce the JsonArray with. */
-	public JsonArray(final Collection<?> collection){
-		super(collection);
-	}
+    /**
+     * Instantiate a new JsonArray using ArrayList's constructor of the same
+     * type.
+     * 
+     * @param collection represents the elements to produce the JsonArray with.
+     */
+    public JsonArray(final Collection<?> collection) {
+        super(collection);
+    }
 
-	/** A convenience method that assumes every element of the JsonArray is castable to T before adding it to a
-	 * collection of Ts.
-	 * @param <T> represents the type that all of the elements of the JsonArray should be cast to and the type the
-	 *        collection will contain.
-	 * @param destination represents where all of the elements of the JsonArray are added to after being cast to the
-	 *        generic type
-	 *        provided.
-	 * @throws ClassCastException if the unchecked cast of an element to T fails. */
-	@SuppressWarnings("unchecked")
-	public <T> void asCollection(final Collection<T> destination){
-		for(final Object o : this){
-			destination.add((T)o);
-		}
-	}
+    /**
+     * A convenience method that assumes every element of the JsonArray is
+     * castable to T before adding it to a collection of Ts.
+     * 
+     * @param <T> represents the type that all of the elements of the JsonArray
+     *            should be cast to and the type the collection will contain.
+     * @param destination represents where all of the elements of the JsonArray
+     *            are added to after being cast to the generic type provided.
+     * @throws ClassCastException if the unchecked cast of an element to T
+     *             fails.
+     */
+    @SuppressWarnings("unchecked")
+    public <T> void asCollection(final Collection<T> destination) {
+        for (final Object o : this) {
+            destination.add((T)o);
+        }
+    }
 
-	/** A convenience method that assumes there is a BigDecimal, Number, or String at the given index. If a Number or
-	 * String is there it is used to construct a new BigDecimal.
-	 * @param index representing where the value is expected to be at.
-	 * @return the value stored at the key or the default provided if the key doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return types.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal.
-	 * @see BigDecimal
-	 * @see Number#doubleValue() */
-	public BigDecimal getBigDecimal(final int index){
-		Object returnable = this.get(index);
-		if(returnable instanceof BigDecimal){
-			/* Success there was a BigDecimal. */
-		}else if(returnable instanceof Number){
-			/* A number can be used to construct a BigDecimal. */
-			returnable = new BigDecimal(returnable.toString());
-		}else if(returnable instanceof String){
-			/* A number can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return (BigDecimal)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a BigDecimal, Number, or
+     * String at the given index. If a Number or String is there it is used to
+     * construct a new BigDecimal.
+     * 
+     * @param index representing where the value is expected to be at.
+     * @return the value stored at the key or the default provided if the key
+     *         doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return types.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal.
+     * @see BigDecimal
+     * @see Number#doubleValue()
+     */
+    public BigDecimal getBigDecimal(final int index) {
+        Object returnable = this.get(index);
+        if (returnable instanceof BigDecimal) {
+            /* Success there was a BigDecimal. */
+        } else if (returnable instanceof Number) {
+            /* A number can be used to construct a BigDecimal. */
+            returnable = new BigDecimal(returnable.toString());
+        } else if (returnable instanceof String) {
+            /* A number can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return (BigDecimal)returnable;
+    }
 
-	/** A convenience method that assumes there is a Boolean or String value at the given index.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a boolean.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. */
-	public Boolean getBoolean(final int index){
-		Object returnable = this.get(index);
-		if(returnable instanceof String){
-			returnable = Boolean.valueOf((String)returnable);
-		}
-		return (Boolean)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a Boolean or String value at
+     * the given index.
+     * 
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a boolean.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     */
+    public Boolean getBoolean(final int index) {
+        Object returnable = this.get(index);
+        if (returnable instanceof String) {
+            returnable = Boolean.valueOf((String)returnable);
+        }
+        return (Boolean)returnable;
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given index.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a byte.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Number */
-	public Byte getByte(final int index){
-		Object returnable = this.get(index);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).byteValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given index.
+     * 
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a byte.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Number
+     */
+    public Byte getByte(final int index) {
+        Object returnable = this.get(index);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).byteValue();
+    }
 
-	/** A convenience method that assumes there is a Collection value at the given index.
-	 * @param <T> the kind of collection to expect at the index. Note unless manually added, collection values will be a
-	 *        JsonArray.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a Collection.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Collection */
-	@SuppressWarnings("unchecked")
-	public <T extends Collection<?>> T getCollection(final int index){
-		/* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will
-		 * work. */
-		return (T)this.get(index);
-	}
+    /**
+     * A convenience method that assumes there is a Collection value at the
+     * given index.
+     * 
+     * @param <T> the kind of collection to expect at the index. Note unless
+     *            manually added, collection values will be a JsonArray.
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a Collection.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Collection
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Collection<?>> T getCollection(final int index) {
+        /*
+         * The unchecked warning is suppressed because there is no way of
+         * guaranteeing at compile time the cast will work.
+         */
+        return (T)this.get(index);
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given index.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a double.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Number */
-	public Double getDouble(final int index){
-		Object returnable = this.get(index);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).doubleValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given index.
+     * 
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a double.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Number
+     */
+    public Double getDouble(final int index) {
+        Object returnable = this.get(index);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).doubleValue();
+    }
 
-	/** A convenience method that assumes there is a String value at the given index representing a fully qualified name
-	 * in dot notation of an enum.
-	 * @param index representing where the value is expected to be at.
-	 * @param <T> the Enum type the value at the index is expected to belong to.
-	 * @return the enum based on the string found at the index, or null if the value at the index was null.
-	 * @throws ClassNotFoundException if the element was a String but the declaring enum type couldn't be determined
-	 *         with it.
-	 * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of
-	 *         the wrong type.
-	 * @throws IllegalArgumentException if an enum type was dynamically determined but it doesn't define an enum with
-	 *         the dynamically determined name.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Enum#valueOf(Class, String) */
-	@SuppressWarnings("unchecked")
-	public <T extends Enum<T>> T getEnum(final int index) throws ClassNotFoundException{
-		/* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a
-		 * ClassCastException when returnType is cast to Class<T>, which is expected by the method's contract. */
-		T returnable;
-		final String element;
-		final String[] splitValues;
-		final int numberOfValues;
-		final StringBuilder returnTypeName;
-		final StringBuilder enumName;
-		final Class<T> returnType;
-		/* Make sure the element at the index is a String. */
-		element = this.getString(index);
-		if(element == null){
-			return null;
-		}
-		/* Get the package, class, and enum names. */
-		splitValues = element.split("\\.");
-		numberOfValues = splitValues.length;
-		returnTypeName = new StringBuilder();
-		enumName = new StringBuilder();
-		for(int i = 0; i < numberOfValues; i++){
-			if(i == (numberOfValues - 1)){
-				/* If it is the last split value then it should be the name of the Enum since dots are not allowed in
-				 * enum names. */
-				enumName.append(splitValues[i]);
-			}else if(i == (numberOfValues - 2)){
-				/* If it is the penultimate split value then it should be the end of the package/enum type and not need
-				 * a dot appended to it. */
-				returnTypeName.append(splitValues[i]);
-			}else{
-				/* Must be part of the package/enum type and will need a dot appended to it since they got removed in
-				 * the split. */
-				returnTypeName.append(splitValues[i]);
-				returnTypeName.append(".");
-			}
-		}
-		/* Use the package/class and enum names to get the Enum<T>. */
-		returnType = (Class<T>)Class.forName(returnTypeName.toString());
-		returnable = Enum.valueOf(returnType, enumName.toString());
-		return returnable;
-	}
+    /**
+     * A convenience method that assumes there is a String value at the given
+     * index representing a fully qualified name in dot notation of an enum.
+     * 
+     * @param index representing where the value is expected to be at.
+     * @param <T> the Enum type the value at the index is expected to belong to.
+     * @return the enum based on the string found at the index, or null if the
+     *         value at the index was null.
+     * @throws ClassNotFoundException if the element was a String but the
+     *             declaring enum type couldn't be determined with it.
+     * @throws ClassCastException if the element at the index was not a String
+     *             or if the fully qualified enum name is of the wrong type.
+     * @throws IllegalArgumentException if an enum type was dynamically
+     *             determined but it doesn't define an enum with the dynamically
+     *             determined name.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Enum#valueOf(Class, String)
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Enum<T>> T getEnum(final int index) throws ClassNotFoundException {
+        /*
+         * Supressing the unchecked warning because the returnType is
+         * dynamically identified and could lead to a ClassCastException when
+         * returnType is cast to Class<T>, which is expected by the method's
+         * contract.
+         */
+        T returnable;
+        final String element;
+        final String[] splitValues;
+        final int numberOfValues;
+        final StringBuilder returnTypeName;
+        final StringBuilder enumName;
+        final Class<T> returnType;
+        /* Make sure the element at the index is a String. */
+        element = this.getString(index);
+        if (element == null) {
+            return null;
+        }
+        /* Get the package, class, and enum names. */
+        splitValues = element.split("\\.");
+        numberOfValues = splitValues.length;
+        returnTypeName = new StringBuilder();
+        enumName = new StringBuilder();
+        for (int i = 0; i < numberOfValues; i++) {
+            if (i == (numberOfValues - 1)) {
+                /*
+                 * If it is the last split value then it should be the name of
+                 * the Enum since dots are not allowed in enum names.
+                 */
+                enumName.append(splitValues[i]);
+            } else if (i == (numberOfValues - 2)) {
+                /*
+                 * If it is the penultimate split value then it should be the
+                 * end of the package/enum type and not need a dot appended to
+                 * it.
+                 */
+                returnTypeName.append(splitValues[i]);
+            } else {
+                /*
+                 * Must be part of the package/enum type and will need a dot
+                 * appended to it since they got removed in the split.
+                 */
+                returnTypeName.append(splitValues[i]);
+                returnTypeName.append(".");
+            }
+        }
+        /* Use the package/class and enum names to get the Enum<T>. */
+        returnType = (Class<T>)Class.forName(returnTypeName.toString());
+        returnable = Enum.valueOf(returnType, enumName.toString());
+        return returnable;
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given index.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a float.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Number */
-	public Float getFloat(final int index){
-		Object returnable = this.get(index);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).floatValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given index.
+     * 
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a float.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Number
+     */
+    public Float getFloat(final int index) {
+        Object returnable = this.get(index);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).floatValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given index.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a int.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Number */
-	public Integer getInteger(final int index){
-		Object returnable = this.get(index);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).intValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given index.
+     * 
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a int.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Number
+     */
+    public Integer getInteger(final int index) {
+        Object returnable = this.get(index);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).intValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given index.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a long.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Number */
-	public Long getLong(final int index){
-		Object returnable = this.get(index);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).longValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given index.
+     * 
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a long.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Number
+     */
+    public Long getLong(final int index) {
+        Object returnable = this.get(index);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).longValue();
+    }
 
-	/** A convenience method that assumes there is a Map value at the given index.
-	 * @param <T> the kind of map to expect at the index. Note unless manually added, Map values will be a JsonObject.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a Map.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Map */
-	@SuppressWarnings("unchecked")
-	public <T extends Map<?, ?>> T getMap(final int index){
-		/* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will
-		 * work. */
-		return (T)this.get(index);
-	}
+    /**
+     * A convenience method that assumes there is a Map value at the given
+     * index.
+     * 
+     * @param <T> the kind of map to expect at the index. Note unless manually
+     *            added, Map values will be a JsonObject.
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a Map.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Map
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Map<?, ?>> T getMap(final int index) {
+        /*
+         * The unchecked warning is suppressed because there is no way of
+         * guaranteeing at compile time the cast will work.
+         */
+        return (T)this.get(index);
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given index.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a short.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray.
-	 * @see Number */
-	public Short getShort(final int index){
-		Object returnable = this.get(index);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).shortValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given index.
+     * 
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a short.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     * @see Number
+     */
+    public Short getShort(final int index) {
+        Object returnable = this.get(index);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).shortValue();
+    }
 
-	/** A convenience method that assumes there is a Boolean, Number, or String value at the given index.
-	 * @param index represents where the value is expected to be at.
-	 * @return the value at the index provided cast to a String.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. */
-	public String getString(final int index){
-		Object returnable = this.get(index);
-		if(returnable instanceof Boolean){
-			returnable = returnable.toString();
-		}else if(returnable instanceof Number){
-			returnable = returnable.toString();
-		}
-		return (String)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a Boolean, Number, or String
+     * value at the given index.
+     * 
+     * @param index represents where the value is expected to be at.
+     * @return the value at the index provided cast to a String.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws IndexOutOfBoundsException if the index is outside of the range of
+     *             element indexes in the JsonArray.
+     */
+    public String getString(final int index) {
+        Object returnable = this.get(index);
+        if (returnable instanceof Boolean) {
+            returnable = returnable.toString();
+        } else if (returnable instanceof Number) {
+            returnable = returnable.toString();
+        }
+        return (String)returnable;
+    }
 
-	/* (non-Javadoc)
-	 * @see org.apache.camel.util.json.Jsonable#asJsonString() */
-	@Override
-	public String toJson(){
-		final StringWriter writable = new StringWriter();
-		try{
-			this.toJson(writable);
-		}catch(final IOException caught){
-			/* See java.io.StringWriter. */
-		}
-		return writable.toString();
-	}
+    /*
+     * (non-Javadoc)
+     * @see org.apache.camel.util.json.Jsonable#asJsonString()
+     */
+    @Override
+    public String toJson() {
+        final StringWriter writable = new StringWriter();
+        try {
+            this.toJson(writable);
+        } catch (final IOException caught) {
+            /* See java.io.StringWriter. */
+        }
+        return writable.toString();
+    }
 
-	/* (non-Javadoc)
-	 * @see org.apache.camel.util.json.Jsonable#toJsonString(java.io.Writer) */
-	@Override
-	public void toJson(final Writer writable) throws IOException{
-		boolean isFirstElement = true;
-		final Iterator<Object> elements = this.iterator();
-		writable.write('[');
-		while(elements.hasNext()){
-			if(isFirstElement){
-				isFirstElement = false;
-			}else{
-				writable.write(',');
-			}
-			writable.write(Jsoner.serialize(elements.next()));
-		}
-		writable.write(']');
-	}
+    /*
+     * (non-Javadoc)
+     * @see org.apache.camel.util.json.Jsonable#toJsonString(java.io.Writer)
+     */
+    @Override
+    public void toJson(final Writer writable) throws IOException {
+        boolean isFirstElement = true;
+        final Iterator<Object> elements = this.iterator();
+        writable.write('[');
+        while (elements.hasNext()) {
+            if (isFirstElement) {
+                isFirstElement = false;
+            } else {
+                writable.write(',');
+            }
+            writable.write(Jsoner.serialize(elements.next()));
+        }
+        writable.write(']');
+    }
 }
diff --git a/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java b/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
index c097f10..42c98f3 100644
--- a/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
+++ b/camel-util-json/src/main/java/org/apache/camel/util/json/JsonObject.java
@@ -1,13 +1,19 @@
-/* Copyright 2016 Clifton Labs
- * Licensed 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
+/**
+ * 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. */
+ * limitations under the License.
+ */
 package org.apache.camel.util.json;
 
 import java.io.IOException;
@@ -15,641 +21,840 @@ import java.io.StringWriter;
 import java.io.Writer;
 import java.math.BigDecimal;
 import java.util.Collection;
-import java.util.LinkedHashMap;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
-/** JsonObject is a common non-thread safe data format for string to data mappings. The contents of a JsonObject are
- * only validated as JSON values on serialization.
+/**
+ * JsonObject is a common non-thread safe data format for string to data
+ * mappings. The contents of a JsonObject are only validated as JSON values on
+ * serialization.
+ * 
  * @see Jsoner
- * @since 2.0.0 */
-public class JsonObject extends LinkedHashMap<String, Object> implements Jsonable{
-	/** The serialization version this class is compatible
-	 * with. This value doesn't need to be incremented if and only if the only changes to occur were updating comments,
-	 * updating javadocs, adding new
-	 * fields to the class, changing the fields from static to non-static, or changing the fields from transient to non
-	 * transient. All other changes require this number be incremented. */
-	private static final long serialVersionUID = 1L;
+ * @since 2.0.0
+ */
+public class JsonObject extends LinkedHashMap<String, Object> implements Jsonable {
+    /**
+     * The serialization version this class is compatible with. This value
+     * doesn't need to be incremented if and only if the only changes to occur
+     * were updating comments, updating javadocs, adding new fields to the
+     * class, changing the fields from static to non-static, or changing the
+     * fields from transient to non transient. All other changes require this
+     * number be incremented.
+     */
+    private static final long serialVersionUID = 1L;
 
-	/** Instantiates an empty JsonObject. */
-	public JsonObject(){
-		super();
-	}
+    /** Instantiates an empty JsonObject. */
+    public JsonObject() {
+        super();
+    }
 
-	/** Instantiate a new JsonObject by accepting a map's entries, which could lead to de/serialization issues of the
-	 * resulting JsonObject since the entry values aren't validated as JSON values.
-	 * @param map represents the mappings to produce the JsonObject with. */
-	public JsonObject(final Map<String, ?> map){
-		super(map);
-	}
+    /**
+     * Instantiate a new JsonObject by accepting a map's entries, which could
+     * lead to de/serialization issues of the resulting JsonObject since the
+     * entry values aren't validated as JSON values.
+     * 
+     * @param map represents the mappings to produce the JsonObject with.
+     */
+    public JsonObject(final Map<String, ?> map) {
+        super(map);
+    }
 
-	/** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is
-	 * there
-	 * its Number#toString() is used to construct a new BigDecimal(String). If a String is there it is used to
-	 * construct a new BigDecimal(String).
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key.
-	 * @throws ClassCastException if the value didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see BigDecimal
-	 * @see Number#toString() */
-	public BigDecimal getBigDecimal(final String key){
-		Object returnable = this.get(key);
-		if(returnable instanceof BigDecimal){
-			/* Success there was a BigDecimal or it defaulted. */
-		}else if(returnable instanceof Number){
-			/* A number can be used to construct a BigDecimal */
-			returnable = new BigDecimal(returnable.toString());
-		}else if(returnable instanceof String){
-			/* A number can be used to construct a BigDecimal */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return (BigDecimal)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a BigDecimal, Number, or
+     * String at the given key. If a Number is there its Number#toString() is
+     * used to construct a new BigDecimal(String). If a String is there it is
+     * used to construct a new BigDecimal(String).
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key.
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see BigDecimal
+     * @see Number#toString()
+     */
+    public BigDecimal getBigDecimal(final String key) {
+        Object returnable = this.get(key);
+        if (returnable instanceof BigDecimal) {
+            /* Success there was a BigDecimal or it defaulted. */
+        } else if (returnable instanceof Number) {
+            /* A number can be used to construct a BigDecimal */
+            returnable = new BigDecimal(returnable.toString());
+        } else if (returnable instanceof String) {
+            /* A number can be used to construct a BigDecimal */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return (BigDecimal)returnable;
+    }
 
-	/** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is
-	 * there
-	 * its Number#toString() is used to construct a new BigDecimal(String). If a String is there it is used to
-	 * construct a new BigDecimal(String).
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key or the default provided if the key doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return types.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see BigDecimal
-	 * @see Number#toString() */
-	public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable instanceof BigDecimal){
-			/* Success there was a BigDecimal or it defaulted. */
-		}else if(returnable instanceof Number){
-			/* A number can be used to construct a BigDecimal */
-			returnable = new BigDecimal(returnable.toString());
-		}else if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return (BigDecimal)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a BigDecimal, Number, or
+     * String at the given key. If a Number is there its Number#toString() is
+     * used to construct a new BigDecimal(String). If a String is there it is
+     * used to construct a new BigDecimal(String).
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key or the default provided if the key
+     *         doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return types.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see BigDecimal
+     * @see Number#toString()
+     */
+    public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable instanceof BigDecimal) {
+            /* Success there was a BigDecimal or it defaulted. */
+        } else if (returnable instanceof Number) {
+            /* A number can be used to construct a BigDecimal */
+            returnable = new BigDecimal(returnable.toString());
+        } else if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return (BigDecimal)returnable;
+    }
 
-	/** A convenience method that assumes there is a Boolean or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key.
-	 * @throws ClassCastException if the value didn't match the assumed return type. */
-	public Boolean getBoolean(final String key){
-		Object returnable = this.get(key);
-		if(returnable instanceof String){
-			returnable = Boolean.valueOf((String)returnable);
-		}
-		return (Boolean)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a Boolean or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key.
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     */
+    public Boolean getBoolean(final String key) {
+        Object returnable = this.get(key);
+        if (returnable instanceof String) {
+            returnable = Boolean.valueOf((String)returnable);
+        }
+        return (Boolean)returnable;
+    }
 
-	/** A convenience method that assumes there is a Boolean or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key or the default provided if the key doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type. */
-	public Boolean getBooleanOrDefault(final String key, final boolean defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable instanceof String){
-			returnable = Boolean.valueOf((String)returnable);
-		}
-		return (Boolean)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a Boolean or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key or the default provided if the key
+     *         doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     */
+    public Boolean getBooleanOrDefault(final String key, final boolean defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable instanceof String) {
+            returnable = Boolean.valueOf((String)returnable);
+        }
+        return (Boolean)returnable;
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key (which may involve rounding or truncation).
-	 * @throws ClassCastException if the value didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#byteValue() */
-	public Byte getByte(final String key){
-		Object returnable = this.get(key);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).byteValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation).
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#byteValue()
+     */
+    public Byte getByte(final String key) {
+        Object returnable = this.get(key);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).byteValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key
-	 *         doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#byteValue() */
-	public Byte getByteOrDefault(final String key, final byte defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).byteValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation) or the default provided if the key doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#byteValue()
+     */
+    public Byte getByteOrDefault(final String key, final byte defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).byteValue();
+    }
 
-	/** A convenience method that assumes there is a Collection at the given key.
-	 * @param <T> the kind of collection to expect at the key. Note unless manually added, collection values will be a
-	 *        JsonArray.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key.
-	 * @throws ClassCastException if the value didn't match the assumed return type. */
-	@SuppressWarnings("unchecked")
-	public <T extends Collection<?>> T getCollection(final String key){
-		/* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will
-		 * work. */
-		return (T)this.get(key);
-	}
+    /**
+     * A convenience method that assumes there is a Collection at the given key.
+     * 
+     * @param <T> the kind of collection to expect at the key. Note unless
+     *            manually added, collection values will be a JsonArray.
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key.
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Collection<?>> T getCollection(final String key) {
+        /*
+         * The unchecked warning is suppressed because there is no way of
+         * guaranteeing at compile time the cast will work.
+         */
+        return (T)this.get(key);
+    }
 
-	/** A convenience method that assumes there is a Collection at the given key.
-	 * @param <T> the kind of collection to expect at the key. Note unless manually added, collection values will be a
-	 *        JsonArray.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key or the default provided if the key doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type. */
-	@SuppressWarnings("unchecked")
-	public <T extends Collection<?>> T getCollectionOrDefault(final String key, final T defaultValue){
-		/* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will
-		 * work. */
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		return (T)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a Collection at the given key.
+     * 
+     * @param <T> the kind of collection to expect at the key. Note unless
+     *            manually added, collection values will be a JsonArray.
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key or the default provided if the key
+     *         doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Collection<?>> T getCollectionOrDefault(final String key, final T defaultValue) {
+        /*
+         * The unchecked warning is suppressed because there is no way of
+         * guaranteeing at compile time the cast will work.
+         */
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        return (T)returnable;
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key (which may involve rounding or truncation).
-	 * @throws ClassCastException if the value didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#doubleValue() */
-	public Double getDouble(final String key){
-		Object returnable = this.get(key);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).doubleValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation).
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#doubleValue()
+     */
+    public Double getDouble(final String key) {
+        Object returnable = this.get(key);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).doubleValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key
-	 *         doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#doubleValue() */
-	public Double getDoubleOrDefault(final String key, final double defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).doubleValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation) or the default provided if the key doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#doubleValue()
+     */
+    public Double getDoubleOrDefault(final String key, final double defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).doubleValue();
+    }
 
-	/** A convenience method that assumes there is a String value at the given key representing a fully qualified name
-	 * in
-	 * dot notation of an enum.
-	 * @param key representing where the value ought to be stored at.
-	 * @param <T> the Enum type the value at the key is expected to belong to.
-	 * @return the enum based on the string found at the key, or null if the value paired with the provided key is null.
-	 * @throws ClassNotFoundException if the value was a String but the declaring enum type couldn't be determined with
-	 *         it.
-	 * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of
-	 *         the wrong type.
-	 * @throws IllegalArgumentException if an enum type was determined but it doesn't define an enum with the determined
-	 *         name.
-	 * @see Enum#valueOf(Class, String) */
-	@SuppressWarnings("unchecked")
-	public <T extends Enum<T>> T getEnum(final String key) throws ClassNotFoundException{
-		/* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a
-		 * ClassCastException when returnType is cast to Class<T>, which is expected by the method's contract. */
-		T returnable;
-		final String value;
-		final String[] splitValues;
-		final int numberOfSplitValues;
-		final StringBuilder returnTypeName;
-		final StringBuilder enumName;
-		final Class<T> returnType;
-		/* Make sure the value at the key is a String. */
-		value = this.getStringOrDefault(key, "");
-		if(value == null){
-			return null;
-		}
-		/* Get the package, class, and enum names. */
-		splitValues = value.split("\\.");
-		numberOfSplitValues = splitValues.length;
-		returnTypeName = new StringBuilder();
-		enumName = new StringBuilder();
-		for(int i = 0; i < numberOfSplitValues; i++){
-			if(i == (numberOfSplitValues - 1)){
-				/* If it is the last split value then it should be the name of the Enum since dots are not allowed
-				 * in enum names. */
-				enumName.append(splitValues[i]);
-			}else if(i == (numberOfSplitValues - 2)){
-				/* If it is the penultimate split value then it should be the end of the package/enum type and not
-				 * need a dot appended to it. */
-				returnTypeName.append(splitValues[i]);
-			}else{
-				/* Must be part of the package/enum type and will need a dot appended to it since they got removed
-				 * in the split. */
-				returnTypeName.append(splitValues[i]);
-				returnTypeName.append(".");
-			}
-		}
-		/* Use the package/class and enum names to get the Enum<T>. */
-		returnType = (Class<T>)Class.forName(returnTypeName.toString());
-		returnable = Enum.valueOf(returnType, enumName.toString());
-		return returnable;
-	}
+    /**
+     * A convenience method that assumes there is a String value at the given
+     * key representing a fully qualified name in dot notation of an enum.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param <T> the Enum type the value at the key is expected to belong to.
+     * @return the enum based on the string found at the key, or null if the
+     *         value paired with the provided key is null.
+     * @throws ClassNotFoundException if the value was a String but the
+     *             declaring enum type couldn't be determined with it.
+     * @throws ClassCastException if the element at the index was not a String
+     *             or if the fully qualified enum name is of the wrong type.
+     * @throws IllegalArgumentException if an enum type was determined but it
+     *             doesn't define an enum with the determined name.
+     * @see Enum#valueOf(Class, String)
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Enum<T>> T getEnum(final String key) throws ClassNotFoundException {
+        /*
+         * Supressing the unchecked warning because the returnType is
+         * dynamically identified and could lead to a ClassCastException when
+         * returnType is cast to Class<T>, which is expected by the method's
+         * contract.
+         */
+        T returnable;
+        final String value;
+        final String[] splitValues;
+        final int numberOfSplitValues;
+        final StringBuilder returnTypeName;
+        final StringBuilder enumName;
+        final Class<T> returnType;
+        /* Make sure the value at the key is a String. */
+        value = this.getStringOrDefault(key, "");
+        if (value == null) {
+            return null;
+        }
+        /* Get the package, class, and enum names. */
+        splitValues = value.split("\\.");
+        numberOfSplitValues = splitValues.length;
+        returnTypeName = new StringBuilder();
+        enumName = new StringBuilder();
+        for (int i = 0; i < numberOfSplitValues; i++) {
+            if (i == (numberOfSplitValues - 1)) {
+                /*
+                 * If it is the last split value then it should be the name of
+                 * the Enum since dots are not allowed in enum names.
+                 */
+                enumName.append(splitValues[i]);
+            } else if (i == (numberOfSplitValues - 2)) {
+                /*
+                 * If it is the penultimate split value then it should be the
+                 * end of the package/enum type and not need a dot appended to
+                 * it.
+                 */
+                returnTypeName.append(splitValues[i]);
+            } else {
+                /*
+                 * Must be part of the package/enum type and will need a dot
+                 * appended to it since they got removed in the split.
+                 */
+                returnTypeName.append(splitValues[i]);
+                returnTypeName.append(".");
+            }
+        }
+        /* Use the package/class and enum names to get the Enum<T>. */
+        returnType = (Class<T>)Class.forName(returnTypeName.toString());
+        returnable = Enum.valueOf(returnType, enumName.toString());
+        return returnable;
+    }
 
-	/** A convenience method that assumes there is a String value at the given key representing a fully qualified name
-	 * in
-	 * dot notation of an enum.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @param <T> the Enum type the value at the key is expected to belong to.
-	 * @return the enum based on the string found at the key, or the defaultValue provided if the key doesn't exist, or
-	 *         null if the value paired with provided key is null.
-	 * @throws ClassNotFoundException if the value was a String but the declaring enum type couldn't be determined with
-	 *         it.
-	 * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of
-	 *         the wrong type.
-	 * @throws IllegalArgumentException if an enum type was determined but it doesn't define an enum with the determined
-	 *         name.
-	 * @see Enum#valueOf(Class, String) */
-	@SuppressWarnings("unchecked")
-	public <T extends Enum<T>> T getEnumOrDefault(final String key, final T defaultValue) throws ClassNotFoundException{
-		/* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a
-		 * ClassCastException when returnType is cast to Class<T>, which is expected by the method's contract. */
-		T returnable;
-		final String value;
-		final String[] splitValues;
-		final int numberOfSplitValues;
-		final StringBuilder returnTypeName;
-		final StringBuilder enumName;
-		final Class<T> returnType;
-		/* Check to make sure the key wasn't actually there and wasn't coincidentally the defaulted String as its
-		 * value. */
-		if(this.containsKey(key)){
-			/* Make sure the value at the key is a String. */
-			value = this.getStringOrDefault(key, "");
-			if(value == null){
-				return null;
-			}
-			/* Get the package, class, and enum names. */
-			splitValues = value.split("\\.");
-			numberOfSplitValues = splitValues.length;
-			returnTypeName = new StringBuilder();
-			enumName = new StringBuilder();
-			for(int i = 0; i < numberOfSplitValues; i++){
-				if(i == (numberOfSplitValues - 1)){
-					/* If it is the last split value then it should be the name of the Enum since dots are not allowed
-					 * in enum names. */
-					enumName.append(splitValues[i]);
-				}else if(i == (numberOfSplitValues - 2)){
-					/* If it is the penultimate split value then it should be the end of the package/enum type and not
-					 * need a dot appended to it. */
-					returnTypeName.append(splitValues[i]);
-				}else{
-					/* Must be part of the package/enum type and will need a dot appended to it since they got removed
-					 * in the split. */
-					returnTypeName.append(splitValues[i]);
-					returnTypeName.append(".");
-				}
-			}
-			/* Use the package/class and enum names to get the Enum<T>. */
-			returnType = (Class<T>)Class.forName(returnTypeName.toString());
-			returnable = Enum.valueOf(returnType, enumName.toString());
-		}else{
-			/* It wasn't there and according to the method's contract we return the default value. */
-			return defaultValue;
-		}
-		return returnable;
-	}
+    /**
+     * A convenience method that assumes there is a String value at the given
+     * key representing a fully qualified name in dot notation of an enum.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @param <T> the Enum type the value at the key is expected to belong to.
+     * @return the enum based on the string found at the key, or the
+     *         defaultValue provided if the key doesn't exist, or null if the
+     *         value paired with provided key is null.
+     * @throws ClassNotFoundException if the value was a String but the
+     *             declaring enum type couldn't be determined with it.
+     * @throws ClassCastException if the element at the index was not a String
+     *             or if the fully qualified enum name is of the wrong type.
+     * @throws IllegalArgumentException if an enum type was determined but it
+     *             doesn't define an enum with the determined name.
+     * @see Enum#valueOf(Class, String)
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Enum<T>> T getEnumOrDefault(final String key, final T defaultValue) throws ClassNotFoundException {
+        /*
+         * Supressing the unchecked warning because the returnType is
+         * dynamically identified and could lead to a ClassCastException when
+         * returnType is cast to Class<T>, which is expected by the method's
+         * contract.
+         */
+        T returnable;
+        final String value;
+        final String[] splitValues;
+        final int numberOfSplitValues;
+        final StringBuilder returnTypeName;
+        final StringBuilder enumName;
+        final Class<T> returnType;
+        /*
+         * Check to make sure the key wasn't actually there and wasn't
+         * coincidentally the defaulted String as its value.
+         */
+        if (this.containsKey(key)) {
+            /* Make sure the value at the key is a String. */
+            value = this.getStringOrDefault(key, "");
+            if (value == null) {
+                return null;
+            }
+            /* Get the package, class, and enum names. */
+            splitValues = value.split("\\.");
+            numberOfSplitValues = splitValues.length;
+            returnTypeName = new StringBuilder();
+            enumName = new StringBuilder();
+            for (int i = 0; i < numberOfSplitValues; i++) {
+                if (i == (numberOfSplitValues - 1)) {
+                    /*
+                     * If it is the last split value then it should be the name
+                     * of the Enum since dots are not allowed in enum names.
+                     */
+                    enumName.append(splitValues[i]);
+                } else if (i == (numberOfSplitValues - 2)) {
+                    /*
+                     * If it is the penultimate split value then it should be
+                     * the end of the package/enum type and not need a dot
+                     * appended to it.
+                     */
+                    returnTypeName.append(splitValues[i]);
+                } else {
+                    /*
+                     * Must be part of the package/enum type and will need a dot
+                     * appended to it since they got removed in the split.
+                     */
+                    returnTypeName.append(splitValues[i]);
+                    returnTypeName.append(".");
+                }
+            }
+            /* Use the package/class and enum names to get the Enum<T>. */
+            returnType = (Class<T>)Class.forName(returnTypeName.toString());
+            returnable = Enum.valueOf(returnType, enumName.toString());
+        } else {
+            /*
+             * It wasn't there and according to the method's contract we return
+             * the default value.
+             */
+            return defaultValue;
+        }
+        return returnable;
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key (which may involve rounding or truncation).
-	 * @throws ClassCastException if the value didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#floatValue() */
-	public Float getFloat(final String key){
-		Object returnable = this.get(key);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).floatValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation).
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#floatValue()
+     */
+    public Float getFloat(final String key) {
+        Object returnable = this.get(key);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).floatValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key
-	 *         doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#floatValue() */
-	public Float getFloatOrDefault(final String key, final float defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).floatValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation) or the default provided if the key doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#floatValue()
+     */
+    public Float getFloatOrDefault(final String key, final float defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).floatValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key (which may involve rounding or truncation).
-	 * @throws ClassCastException if the value didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#intValue() */
-	public Integer getInteger(final String key){
-		Object returnable = this.get(key);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).intValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation).
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#intValue()
+     */
+    public Integer getInteger(final String key) {
+        Object returnable = this.get(key);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).intValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key
-	 *         doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#intValue() */
-	public Integer getIntegerOrDefault(final String key, final int defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).intValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation) or the default provided if the key doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#intValue()
+     */
+    public Integer getIntegerOrDefault(final String key, final int defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).intValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key (which may involve rounding or truncation).
-	 * @throws ClassCastException if the value didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#longValue() */
-	public Long getLong(final String key){
-		Object returnable = this.get(key);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).longValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation).
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#longValue()
+     */
+    public Long getLong(final String key) {
+        Object returnable = this.get(key);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).longValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key
-	 *         doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#longValue() */
-	public Long getLongOrDefault(final String key, final long defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).longValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation) or the default provided if the key doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#longValue()
+     */
+    public Long getLongOrDefault(final String key, final long defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).longValue();
+    }
 
-	/** A convenience method that assumes there is a Map at the given key.
-	 * @param <T> the kind of map to expect at the key. Note unless manually added, Map values will be a JsonObject.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key.
-	 * @throws ClassCastException if the value didn't match the assumed return type. */
-	@SuppressWarnings("unchecked")
-	public <T extends Map<?, ?>> T getMap(final String key){
-		/* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will
-		 * work. */
-		return (T)this.get(key);
-	}
+    /**
+     * A convenience method that assumes there is a Map at the given key.
+     * 
+     * @param <T> the kind of map to expect at the key. Note unless manually
+     *            added, Map values will be a JsonObject.
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key.
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Map<?, ?>> T getMap(final String key) {
+        /*
+         * The unchecked warning is suppressed because there is no way of
+         * guaranteeing at compile time the cast will work.
+         */
+        return (T)this.get(key);
+    }
 
-	/** A convenience method that assumes there is a Map at the given key.
-	 * @param <T> the kind of map to expect at the key. Note unless manually added, Map values will be a JsonObject.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key or the default provided if the key doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type. */
-	@SuppressWarnings("unchecked")
-	public <T extends Map<?, ?>> T getMapOrDefault(final String key, final T defaultValue){
-		/* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will
-		 * work. */
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			returnable = defaultValue;
-		}
-		return (T)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a Map at the given key.
+     * 
+     * @param <T> the kind of map to expect at the key. Note unless manually
+     *            added, Map values will be a JsonObject.
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key or the default provided if the key
+     *         doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends Map<?, ?>> T getMapOrDefault(final String key, final T defaultValue) {
+        /*
+         * The unchecked warning is suppressed because there is no way of
+         * guaranteeing at compile time the cast will work.
+         */
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            returnable = defaultValue;
+        }
+        return (T)returnable;
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key (which may involve rounding or truncation).
-	 * @throws ClassCastException if the value didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#shortValue() */
-	public Short getShort(final String key){
-		Object returnable = this.get(key);
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).shortValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation).
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#shortValue()
+     */
+    public Short getShort(final String key) {
+        Object returnable = this.get(key);
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).shortValue();
+    }
 
-	/** A convenience method that assumes there is a Number or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key
-	 *         doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type.
-	 * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number
-	 *         represents the double or float Infinity or NaN.
-	 * @see Number#shortValue() */
-	public Short getShortOrDefault(final String key, final short defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable == null){
-			return null;
-		}
-		if(returnable instanceof String){
-			/* A String can be used to construct a BigDecimal. */
-			returnable = new BigDecimal((String)returnable);
-		}
-		return ((Number)returnable).shortValue();
-	}
+    /**
+     * A convenience method that assumes there is a Number or String value at
+     * the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key (which may involve rounding or
+     *         truncation) or the default provided if the key doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     * @throws NumberFormatException if a String isn't a valid representation of
+     *             a BigDecimal or if the Number represents the double or float
+     *             Infinity or NaN.
+     * @see Number#shortValue()
+     */
+    public Short getShortOrDefault(final String key, final short defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable == null) {
+            return null;
+        }
+        if (returnable instanceof String) {
+            /* A String can be used to construct a BigDecimal. */
+            returnable = new BigDecimal((String)returnable);
+        }
+        return ((Number)returnable).shortValue();
+    }
 
-	/** A convenience method that assumes there is a Boolean, Number, or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @return the value stored at the key.
-	 * @throws ClassCastException if the value didn't match the assumed return type. */
-	public String getString(final String key){
-		Object returnable = this.get(key);
-		if(returnable instanceof Boolean){
-			returnable = returnable.toString();
-		}else if(returnable instanceof Number){
-			returnable = returnable.toString();
-		}
-		return (String)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a Boolean, Number, or String
+     * value at the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @return the value stored at the key.
+     * @throws ClassCastException if the value didn't match the assumed return
+     *             type.
+     */
+    public String getString(final String key) {
+        Object returnable = this.get(key);
+        if (returnable instanceof Boolean) {
+            returnable = returnable.toString();
+        } else if (returnable instanceof Number) {
+            returnable = returnable.toString();
+        }
+        return (String)returnable;
+    }
 
-	/** A convenience method that assumes there is a Boolean, Number, or String value at the given key.
-	 * @param key representing where the value ought to be stored at.
-	 * @param defaultValue representing what is returned when the key isn't in the JsonObject.
-	 * @return the value stored at the key or the default provided if the key doesn't exist.
-	 * @throws ClassCastException if there was a value but didn't match the assumed return type. */
-	public String getStringOrDefault(final String key, final String defaultValue){
-		Object returnable;
-		if(this.containsKey(key)){
-			returnable = this.get(key);
-		}else{
-			return defaultValue;
-		}
-		if(returnable instanceof Boolean){
-			returnable = returnable.toString();
-		}else if(returnable instanceof Number){
-			returnable = returnable.toString();
-		}
-		return (String)returnable;
-	}
+    /**
+     * A convenience method that assumes there is a Boolean, Number, or String
+     * value at the given key.
+     * 
+     * @param key representing where the value ought to be stored at.
+     * @param defaultValue representing what is returned when the key isn't in
+     *            the JsonObject.
+     * @return the value stored at the key or the default provided if the key
+     *         doesn't exist.
+     * @throws ClassCastException if there was a value but didn't match the
+     *             assumed return type.
+     */
+    public String getStringOrDefault(final String key, final String defaultValue) {
+        Object returnable;
+        if (this.containsKey(key)) {
+            returnable = this.get(key);
+        } else {
+            return defaultValue;
+        }
+        if (returnable instanceof Boolean) {
+            returnable = returnable.toString();
+        } else if (returnable instanceof Number) {
+            returnable = returnable.toString();
+        }
+        return (String)returnable;
+    }
 
-	/* (non-Javadoc)
-	 * @see org.apache.camel.util.json.Jsonable#asJsonString() */
-	@Override
-	public String toJson(){
-		final StringWriter writable = new StringWriter();
-		try{
-			this.toJson(writable);
-		}catch(final IOException caught){
-			/* See java.io.StringWriter. */
-		}
-		return writable.toString();
-	}
+    /*
+     * (non-Javadoc)
+     * @see org.apache.camel.util.json.Jsonable#asJsonString()
+     */
+    @Override
+    public String toJson() {
+        final StringWriter writable = new StringWriter();
+        try {
+            this.toJson(writable);
+        } catch (final IOException caught) {
+            /* See java.io.StringWriter. */
+        }
+        return writable.toString();
+    }
 
-	/* (non-Javadoc)
-	 * @see org.apache.camel.util.json.Jsonable#toJsonString(java.io.Writer) */
-	@Override
-	public void toJson(final Writer writable) throws IOException{
-		/* Writes the map in JSON object format. */
-		boolean isFirstEntry = true;
-		final Iterator<Map.Entry<String, Object>> entries = this.entrySet().iterator();
-		writable.write('{');
-		while(entries.hasNext()){
-			if(isFirstEntry){
-				isFirstEntry = false;
-			}else{
-				writable.write(',');
-			}
-			final Map.Entry<String, Object> entry = entries.next();
-			writable.write(Jsoner.serialize(entry.getKey()));
-			writable.write(':');
-			writable.write(Jsoner.serialize(entry.getValue()));
-		}
-		writable.write('}');
-	}
+    /*
+     * (non-Javadoc)
+     * @see org.apache.camel.util.json.Jsonable#toJsonString(java.io.Writer)
+     */
+    @Override
+    public void toJson(final Writer writable) throws IOException {
+        /* Writes the map in JSON object format. */
+        boolean isFirstEntry = true;
+        final Iterator<Map.Entry<String, Object>> entries = this.entrySet().iterator();
+        writable.write('{');
+        while (entries.hasNext()) {
+            if (isFirstEntry) {
+                isFirstEntry = false;
+            } else {
+                writable.write(',');
+            }
+            final Map.Entry<String, Object> entry = entries.next();
+            writable.write(Jsoner.serialize(entry.getKey()));
+            writable.write(':');
+            writable.write(Jsoner.serialize(entry.getValue()));
+        }
+        writable.write('}');
+    }
 }
diff --git a/camel-util-json/src/main/java/org/apache/camel/util/json/Jsonable.java b/camel-util-json/src/main/java/org/apache/camel/util/json/Jsonable.java
index ff344d2..09d5484 100644
--- a/camel-util-json/src/main/java/org/apache/camel/util/json/Jsonable.java
+++ b/camel-util-json/src/main/java/org/apache/camel/util/json/Jsonable.java
@@ -1,27 +1,42 @@
-/* Copyright 2016 Clifton Labs
- * Licensed 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
+/**
+ * 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. */
+ * limitations under the License.
+ */
 package org.apache.camel.util.json;
 
 import java.io.IOException;
 import java.io.Writer;
 
-/** Jsonables can be serialized in java script object notation (JSON).
- * @since 2.0.0 */
-public interface Jsonable{
-    /** Serialize to a JSON formatted string.
-     * @return a string, formatted in JSON, that represents the Jsonable. */
-    public String toJson();
+/**
+ * Jsonables can be serialized in java script object notation (JSON).
+ * 
+ * @since 2.0.0
+ */
+public interface Jsonable {
+    /**
+     * Serialize to a JSON formatted string.
+     * 
+     * @return a string, formatted in JSON, that represents the Jsonable.
+     */
+    String toJson();
 
-    /** Serialize to a JSON formatted stream.
+    /**
+     * Serialize to a JSON formatted stream.
+     * 
      * @param writable where the resulting JSON text should be sent.
-     * @throws IOException when the writable encounters an I/O error. */
-    public void toJson(Writer writable) throws IOException;
+     * @throws IOException when the writable encounters an I/O error.
+     */
+    void toJson(Writer writable) throws IOException;
 }
diff --git a/camel-util-json/src/main/java/org/apache/camel/util/json/Jsoner.java b/camel-util-json/src/main/java/org/apache/camel/util/json/Jsoner.java
index 8c518b1..04373f7 100644
--- a/camel-util-json/src/main/java/org/apache/camel/util/json/Jsoner.java
+++ b/camel-util-json/src/main/java/org/apache/camel/util/json/Jsoner.java
@@ -1,13 +1,19 @@
-/* Copyright 2016 Clifton Labs
- * Licensed 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
+/**
+ * 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. */
+ * limitations under the License.
+ */
 package org.apache.camel.util.json;
 
 import java.io.IOException;
@@ -22,839 +28,1015 @@ import java.util.LinkedList;
 import java.util.Map;
 import java.util.Set;
 
-/** Jsoner provides JSON utilities for escaping strings to be JSON compatible, thread safe parsing (RFC 4627) JSON
- * strings, and serializing data to strings in JSON format.
- * @since 2.0.0 */
-public class Jsoner{
-	/** Flags to tweak the behavior of the primary deserialization method. */
-	private static enum DeserializationOptions{
-		/** Whether a multiple JSON values can be deserialized as a root element. */
-		ALLOW_CONCATENATED_JSON_VALUES,
-		/** Whether a JsonArray can be deserialized as a root element. */
-		ALLOW_JSON_ARRAYS,
-		/** Whether a boolean, null, Number, or String can be deserialized as a root element. */
-		ALLOW_JSON_DATA,
-		/** Whether a JsonObject can be deserialized as a root element. */
-		ALLOW_JSON_OBJECTS;
-	}
+/**
+ * Jsoner provides JSON utilities for escaping strings to be JSON compatible,
+ * thread safe parsing (RFC 4627) JSON strings, and serializing data to strings
+ * in JSON format.
+ * 
+ * @since 2.0.0
+ */
+public final class Jsoner {
+    /** Flags to tweak the behavior of the primary deserialization method. */
+    private enum DeserializationOptions {
+        /**
+         * Whether a multiple JSON values can be deserialized as a root element.
+         */
+        ALLOW_CONCATENATED_JSON_VALUES,
+        /** Whether a JsonArray can be deserialized as a root element. */
+        ALLOW_JSON_ARRAYS,
+        /**
+         * Whether a boolean, null, Number, or String can be deserialized as a
+         * root element.
+         */
+        ALLOW_JSON_DATA,
+        /** Whether a JsonObject can be deserialized as a root element. */
+        ALLOW_JSON_OBJECTS;
+    }
 
-	/** Flags to tweak the behavior of the primary serialization method. */
-	private static enum SerializationOptions{
-		/** Instead of aborting serialization on non-JSON values that are Enums it will continue serialization with the
-		 * Enums' "${PACKAGE}.${DECLARING_CLASS}.${NAME}".
-		 * @see Enum */
-		ALLOW_FULLY_QUALIFIED_ENUMERATIONS,
-		/** Instead of aborting serialization on non-JSON values it will continue serialization by serializing the
-		 * non-JSON value directly into the now invalid JSON. Be mindful that invalid JSON will not successfully
-		 * deserialize. */
-		ALLOW_INVALIDS,
-		/** Instead of aborting serialization on non-JSON values that implement Jsonable it will continue serialization
-		 * by deferring serialization to the Jsonable.
-		 * @see Jsonable */
-		ALLOW_JSONABLES,
-		/** Instead of aborting serialization on non-JSON values it will continue serialization by using reflection to
-		 * best describe the value as a JsonObject. */
-		ALLOW_UNDEFINEDS;
-	}
+    /** Flags to tweak the behavior of the primary serialization method. */
+    private enum SerializationOptions {
+        /**
+         * Instead of aborting serialization on non-JSON values that are Enums
+         * it will continue serialization with the Enums'
+         * "${PACKAGE}.${DECLARING_CLASS}.${NAME}".
+         * 
+         * @see Enum
+         */
+        ALLOW_FULLY_QUALIFIED_ENUMERATIONS,
+        /**
+         * Instead of aborting serialization on non-JSON values it will continue
+         * serialization by serializing the non-JSON value directly into the now
+         * invalid JSON. Be mindful that invalid JSON will not successfully
+         * deserialize.
+         */
+        ALLOW_INVALIDS,
+        /**
+         * Instead of aborting serialization on non-JSON values that implement
+         * Jsonable it will continue serialization by deferring serialization to
+         * the Jsonable.
+         * 
+         * @see Jsonable
+         */
+        ALLOW_JSONABLES,
+        /**
+         * Instead of aborting serialization on non-JSON values it will continue
+         * serialization by using reflection to best describe the value as a
+         * JsonObject.
+         */
+        ALLOW_UNDEFINEDS;
+    }
 
-	/** The possible States of a JSON deserializer. */
-	private static enum States{
-		/** Post-parsing state. */
-		DONE,
-		/** Pre-parsing state. */
-		INITIAL,
-		/** Parsing error, ParsingException should be thrown. */
-		PARSED_ERROR,
-		PARSING_ARRAY,
-		/** Parsing a key-value pair inside of an object. */
-		PARSING_ENTRY,
-		PARSING_OBJECT;
-	}
+    /** The possible States of a JSON deserializer. */
+    private enum States {
+        /** Post-parsing state. */
+        DONE,
+        /** Pre-parsing state. */
+        INITIAL,
+        /** Parsing error, ParsingException should be thrown. */
+        PARSED_ERROR, PARSING_ARRAY,
+        /** Parsing a key-value pair inside of an object. */
+        PARSING_ENTRY, PARSING_OBJECT;
+    }
 
-	private Jsoner(){
-		/* Keeping it classy. */
-	}
+    private Jsoner() {
+        /* Keeping it classy. */
+    }
 
-	/** Deserializes a readable stream according to the RFC 4627 JSON specification.
-	 * @param readableDeserializable representing content to be deserialized as JSON.
-	 * @return either a boolean, null, Number, String, JsonObject, or JsonArray that best represents the deserializable.
-	 * @throws DeserializationException if an unexpected token is encountered in the deserializable. To recover from a
-	 *         DeserializationException: fix the deserializable
-	 *         to no longer have an unexpected token and try again.
-	 * @throws IOException if the underlying reader encounters an I/O error. Ensure the reader is properly instantiated,
-	 *         isn't closed, or that it is ready before trying again. */
-	public static Object deserialize(final Reader readableDeserializable) throws DeserializationException, IOException{
-		return Jsoner.deserialize(readableDeserializable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS, DeserializationOptions.ALLOW_JSON_OBJECTS, DeserializationOptions.ALLOW_JSON_DATA)).get(0);
-	}
+    /**
+     * Deserializes a readable stream according to the RFC 4627 JSON
+     * specification.
+     * 
+     * @param readableDeserializable representing content to be deserialized as
+     *            JSON.
+     * @return either a boolean, null, Number, String, JsonObject, or JsonArray
+     *         that best represents the deserializable.
+     * @throws DeserializationException if an unexpected token is encountered in
+     *             the deserializable. To recover from a
+     *             DeserializationException: fix the deserializable to no longer
+     *             have an unexpected token and try again.
+     * @throws IOException if the underlying reader encounters an I/O error.
+     *             Ensure the reader is properly instantiated, isn't closed, or
+     *             that it is ready before trying again.
+     */
+    public static Object deserialize(final Reader readableDeserializable) throws DeserializationException, IOException {
+        return Jsoner.deserialize(readableDeserializable,
+                                  EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS, DeserializationOptions.ALLOW_JSON_OBJECTS, DeserializationOptions.ALLOW_JSON_DATA))
+            .get(0);
+    }
 
-	/** Deserialize a stream with all deserialized JSON values are wrapped in a JsonArray.
-	 * @param deserializable representing content to be deserialized as JSON.
-	 * @param flags representing the allowances and restrictions on deserialization.
-	 * @return the allowable object best represented by the deserializable.
-	 * @throws DeserializationException if a disallowed or unexpected token is encountered in the deserializable. To
-	 *         recover from a DeserializationException: fix the
-	 *         deserializable to no longer have a disallowed or unexpected token and try again.
-	 * @throws IOException if the underlying reader encounters an I/O error. Ensure the reader is properly instantiated,
-	 *         isn't closed, or that it is ready before trying again. */
-	private static JsonArray deserialize(final Reader deserializable, final Set<DeserializationOptions> flags) throws DeserializationException, IOException{
-		final Yylex lexer = new Yylex(deserializable);
-		Yytoken token;
-		States currentState;
-		int returnCount = 1;
-		final LinkedList<States> stateStack = new LinkedList<>();
-		final LinkedList<Object> valueStack = new LinkedList<>();
-		stateStack.addLast(States.INITIAL);
-		//System.out.println("//////////DESERIALIZING//////////");
-		do{
-			/* Parse through the parsable string's tokens. */
-			currentState = Jsoner.popNextState(stateStack);
-			token = Jsoner.lexNextToken(lexer);
-			switch(currentState){
-				case DONE:
-					/* The parse has finished a JSON value. */
-					if(!flags.contains(DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES) || Yytoken.Types.END.equals(token.getType())){
-						/* Break if concatenated values are not allowed or if an END token is read. */
-						break;
-					}
-					/* Increment the amount of returned JSON values and treat the token as if it were a fresh parse. */
-					returnCount += 1;
-					/* Fall through to the case for the initial state. */
-					//$FALL-THROUGH$
-				case INITIAL:
-					/* The parse has just started. */
-					switch(token.getType()){
-						case DATUM:
-							/* A boolean, null, Number, or String could be detected. */
-							if(flags.contains(DeserializationOptions.ALLOW_JSON_DATA)){
-								valueStack.addLast(token.getValue());
-								stateStack.addLast(States.DONE);
-							}else{
-								throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
-							}
-							break;
-						case LEFT_BRACE:
-							/* An object is detected. */
-							if(flags.contains(DeserializationOptions.ALLOW_JSON_OBJECTS)){
-								valueStack.addLast(new JsonObject());
-								stateStack.addLast(States.PARSING_OBJECT);
-							}else{
-								throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
-							}
-							break;
-						case LEFT_SQUARE:
-							/* An array is detected. */
-							if(flags.contains(DeserializationOptions.ALLOW_JSON_ARRAYS)){
-								valueStack.addLast(new JsonArray());
-								stateStack.addLast(States.PARSING_ARRAY);
-							}else{
-								throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
-							}
-							break;
-						default:
-							/* Neither a JSON array or object was detected. */
-							throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
-					}
-					break;
-				case PARSED_ERROR:
-					/* The parse could be in this state due to the state stack not having a state to pop off. */
-					throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
-				case PARSING_ARRAY:
-					switch(token.getType()){
-						case COMMA:
-							/* The parse could detect a comma while parsing an array since it separates each element. */
-							stateStack.addLast(currentState);
-							break;
-						case DATUM:
-							/* The parse found an element of the array. */
-							JsonArray val = (JsonArray)valueStack.getLast();
-							val.add(token.getValue());
-							stateStack.addLast(currentState);
-							break;
-						case LEFT_BRACE:
-							/* The parse found an object in the array. */
-							val = (JsonArray)valueStack.getLast();
-							final JsonObject object = new JsonObject();
-							val.add(object);
-							valueStack.addLast(object);
-							stateStack.addLast(currentState);
-							stateStack.addLast(States.PARSING_OBJECT);
-							break;
-						case LEFT_SQUARE:
-							/* The parse found another array in the array. */
-							val = (JsonArray)valueStack.getLast();
-							final JsonArray array = new JsonArray();
-							val.add(array);
-							valueStack.addLast(array);
-							stateStack.addLast(currentState);
-							stateStack.addLast(States.PARSING_ARRAY);
-							break;
-						case RIGHT_SQUARE:
-							/* The parse found the end of the array. */
-							if(valueStack.size() > returnCount){
-								valueStack.removeLast();
-							}else{
-								/* The parse has been fully resolved. */
-								stateStack.addLast(States.DONE);
-							}
-							break;
-						default:
-							/* Any other token is invalid in an array. */
-							throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
-					}
-					break;
-				case PARSING_OBJECT:
-					/* The parse has detected the start of an object. */
-					switch(token.getType()){
-						case COMMA:
-							/* The parse could detect a comma while parsing an object since it separates each key value
-							 * pair. Continue parsing the object. */
-							stateStack.addLast(currentState);
-							break;
-						case DATUM:
-							/* The token ought to be a key. */
-							if(token.getValue() instanceof String){
-								/* JSON keys are always strings, strings are not always JSON keys but it is going to be
-								 * treated as one. Continue parsing the object. */
-								final String key = (String)token.getValue();
-								valueStack.addLast(key);
-								stateStack.addLast(currentState);
-								stateStack.addLast(States.PARSING_ENTRY);
-							}else{
-								/* Abort! JSON keys are always strings and it wasn't a string. */
-								throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
-							}
-							break;
-						case RIGHT_BRACE:
-							/* The parse has found the end of the object. */
-							if(valueStack.size() > returnCount){
-								/* There are unresolved values remaining. */
-								valueStack.removeLast();
-							}else{
-								/* The parse has been fully resolved. */
-								stateStack.addLast(States.DONE);
-							}
-							break;
-						default:
-							/* The parse didn't detect the end of an object or a key. */
-							throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
-					}
-					break;
-				case PARSING_ENTRY:
-					switch(token.getType()){
-						/* Parsed pair keys can only happen while parsing objects. */
-						case COLON:
-							/* The parse could detect a colon while parsing a key value pair since it separates the key
-							 * and value from each other. Continue parsing the entry. */
-							stateStack.addLast(currentState);
-							break;
-						case DATUM:
-							/* The parse has found a value for the parsed pair key. */
-							String key = (String)valueStack.removeLast();
-							JsonObject parent = (JsonObject)valueStack.getLast();
-							parent.put(key, token.getValue());
-							break;
-						case LEFT_BRACE:
-							/* The parse has found an object for the parsed pair key. */
-							key = (String)valueStack.removeLast();
-							parent = (JsonObject)valueStack.getLast();
-							final JsonObject object = new JsonObject();
-							parent.put(key, object);
-							valueStack.addLast(object);
-							stateStack.addLast(States.PARSING_OBJECT);
-							break;
-						case LEFT_SQUARE:
-							/* The parse has found an array for the parsed pair key. */
-							key = (String)valueStack.removeLast();
-							parent = (JsonObject)valueStack.getLast();
-							final JsonArray array = new JsonArray();
-							parent.put(key, array);
-							valueStack.addLast(array);
-							stateStack.addLast(States.PARSING_ARRAY);
-							break;
-						default:
-							/* The parse didn't find anything for the parsed pair key. */
-							throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
-					}
-					break;
-				default:
-					break;
-			}
-			//System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~");
-			//System.out.println(currentState);
-			//System.out.println(token);
-			//System.out.println(valueStack);
-			//System.out.println(stateStack);
-			/* If we're not at the END and DONE then do the above again. */
-		}while(!(States.DONE.equals(currentState) && Yytoken.Types.END.equals(token.getType())));
-		//System.out.println("!!!!!!!!!!DESERIALIZED!!!!!!!!!!");
-		return new JsonArray(valueStack);
-	}
+    /**
+     * Deserialize a stream with all deserialized JSON values are wrapped in a
+     * JsonArray.
+     * 
+     * @param deserializable representing content to be deserialized as JSON.
+     * @param flags representing the allowances and restrictions on
+     *            deserialization.
+     * @return the allowable object best represented by the deserializable.
+     * @throws DeserializationException if a disallowed or unexpected token is
+     *             encountered in the deserializable. To recover from a
+     *             DeserializationException: fix the deserializable to no longer
+     *             have a disallowed or unexpected token and try again.
+     * @throws IOException if the underlying reader encounters an I/O error.
+     *             Ensure the reader is properly instantiated, isn't closed, or
+     *             that it is ready before trying again.
+     */
+    private static JsonArray deserialize(final Reader deserializable, final Set<DeserializationOptions> flags) throws DeserializationException, IOException {
+        final Yylex lexer = new Yylex(deserializable);
+        Yytoken token;
+        States currentState;
+        int returnCount = 1;
+        final LinkedList<States> stateStack = new LinkedList<>();
+        final LinkedList<Object> valueStack = new LinkedList<>();
+        stateStack.addLast(States.INITIAL);
+        do {
+            /* Parse through the parsable string's tokens. */
+            currentState = Jsoner.popNextState(stateStack);
+            token = Jsoner.lexNextToken(lexer);
+            switch (currentState) {
+            case DONE:
+                /* The parse has finished a JSON value. */
+                if (!flags.contains(DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES) || Yytoken.Types.END.equals(token.getType())) {
+                    /*
+                     * Break if concatenated values are not allowed or if an END
+                     * token is read.
+                     */
+                    break;
+                }
+                /*
+                 * Increment the amount of returned JSON values and treat the
+                 * token as if it were a fresh parse.
+                 */
+                returnCount += 1;
+                /* Fall through to the case for the initial state. */
+                //$FALL-THROUGH$
+            case INITIAL:
+                /* The parse has just started. */
+                switch (token.getType()) {
+                case DATUM:
+                    /* A boolean, null, Number, or String could be detected. */
+                    if (flags.contains(DeserializationOptions.ALLOW_JSON_DATA)) {
+                        valueStack.addLast(token.getValue());
+                        stateStack.addLast(States.DONE);
+                    } else {
+                        throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
+                    }
+                    break;
+                case LEFT_BRACE:
+                    /* An object is detected. */
+                    if (flags.contains(DeserializationOptions.ALLOW_JSON_OBJECTS)) {
+                        valueStack.addLast(new JsonObject());
+                        stateStack.addLast(States.PARSING_OBJECT);
+                    } else {
+                        throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
+                    }
+                    break;
+                case LEFT_SQUARE:
+                    /* An array is detected. */
+                    if (flags.contains(DeserializationOptions.ALLOW_JSON_ARRAYS)) {
+                        valueStack.addLast(new JsonArray());
+                        stateStack.addLast(States.PARSING_ARRAY);
+                    } else {
+                        throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
+                    }
+                    break;
+                default:
+                    /* Neither a JSON array or object was detected. */
+                    throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
+                }
+                break;
+            case PARSED_ERROR:
+                /*
+                 * The parse could be in this state due to the state stack not
+                 * having a state to pop off.
+                 */
+                throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
+            case PARSING_ARRAY:
+                switch (token.getType()) {
+                case COMMA:
+                    /*
+                     * The parse could detect a comma while parsing an array
+                     * since it separates each element.
+                     */
+                    stateStack.addLast(currentState);
+                    break;
+                case DATUM:
+                    /* The parse found an element of the array. */
+                    JsonArray val = (JsonArray)valueStack.getLast();
+                    val.add(token.getValue());
+                    stateStack.addLast(currentState);
+                    break;
+                case LEFT_BRACE:
+                    /* The parse found an object in the array. */
+                    val = (JsonArray)valueStack.getLast();
+                    final JsonObject object = new JsonObject();
+                    val.add(object);
+                    valueStack.addLast(object);
+                    stateStack.addLast(currentState);
+                    stateStack.addLast(States.PARSING_OBJECT);
+                    break;
+                case LEFT_SQUARE:
+                    /* The parse found another array in the array. */
+                    val = (JsonArray)valueStack.getLast();
+                    final JsonArray array = new JsonArray();
+                    val.add(array);
+                    valueStack.addLast(array);
+                    stateStack.addLast(currentState);
+                    stateStack.addLast(States.PARSING_ARRAY);
+                    break;
+                case RIGHT_SQUARE:
+                    /* The parse found the end of the array. */
+                    if (valueStack.size() > returnCount) {
+                        valueStack.removeLast();
+                    } else {
+                        /* The parse has been fully resolved. */
+                        stateStack.addLast(States.DONE);
+                    }
+                    break;
+                default:
+                    /* Any other token is invalid in an array. */
+                    throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
+                }
+                break;
+            case PARSING_OBJECT:
+                /* The parse has detected the start of an object. */
+                switch (token.getType()) {
+                case COMMA:
+                    /*
+                     * The parse could detect a comma while parsing an object
+                     * since it separates each key value pair. Continue parsing
+                     * the object.
+                     */
+                    stateStack.addLast(currentState);
+                    break;
+                case DATUM:
+                    /* The token ought to be a key. */
+                    if (token.getValue() instanceof String) {
+                        /*
+                         * JSON keys are always strings, strings are not always
+                         * JSON keys but it is going to be treated as one.
+                         * Continue parsing the object.
+                         */
+                        final String key = (String)token.getValue();
+                        valueStack.addLast(key);
+                        stateStack.addLast(currentState);
+                        stateStack.addLast(States.PARSING_ENTRY);
+                    } else {
+                        /*
+                         * Abort! JSON keys are always strings and it wasn't a
+                         * string.
+                         */
+                        throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
+                    }
+                    break;
+                case RIGHT_BRACE:
+                    /* The parse has found the end of the object. */
+                    if (valueStack.size() > returnCount) {
+                        /* There are unresolved values remaining. */
+                        valueStack.removeLast();
+                    } else {
+                        /* The parse has been fully resolved. */
+                        stateStack.addLast(States.DONE);
+                    }
+                    break;
+                default:
+                    /* The parse didn't detect the end of an object or a key. */
+                    throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
+                }
+                break;
+            case PARSING_ENTRY:
+                switch (token.getType()) {
+                /* Parsed pair keys can only happen while parsing objects. */
+                case COLON:
+                    /*
+                     * The parse could detect a colon while parsing a key value
+                     * pair since it separates the key and value from each
+                     * other. Continue parsing the entry.
+                     */
+                    stateStack.addLast(currentState);
+                    break;
+                case DATUM:
+                    /* The parse has found a value for the parsed pair key. */
+                    String key = (String)valueStack.removeLast();
+                    JsonObject parent = (JsonObject)valueStack.getLast();
+                    parent.put(key, token.getValue());
+                    break;
+                case LEFT_BRACE:
+                    /* The parse has found an object for the parsed pair key. */
+                    key = (String)valueStack.removeLast();
+                    parent = (JsonObject)valueStack.getLast();
+                    final JsonObject object = new JsonObject();
+                    parent.put(key, object);
+                    valueStack.addLast(object);
+                    stateStack.addLast(States.PARSING_OBJECT);
+                    break;
+                case LEFT_SQUARE:
+                    /* The parse has found an array for the parsed pair key. */
+                    key = (String)valueStack.removeLast();
+                    parent = (JsonObject)valueStack.getLast();
+                    final JsonArray array = new JsonArray();
+                    parent.put(key, array);
+                    valueStack.addLast(array);
+                    stateStack.addLast(States.PARSING_ARRAY);
+                    break;
+                default:
+                    /*
+                     * The parse didn't find anything for the parsed pair key.
+                     */
+                    throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
+                }
+                break;
+            default:
+                break;
+            }
+            /* If we're not at the END and DONE then do the above again. */
+        } while (!(States.DONE.equals(currentState) && Yytoken.Types.END.equals(token.getType())));
+        return new JsonArray(valueStack);
+    }
 
-	/** A convenience method that assumes a StringReader to deserialize a string.
-	 * @param deserializable representing content to be deserialized as JSON.
-	 * @return either a boolean, null, Number, String, JsonObject, or JsonArray that best represents the deserializable.
-	 * @throws DeserializationException if an unexpected token is encountered in the deserializable. To recover from a
-	 *         DeserializationException: fix the deserializable
-	 *         to no longer have an unexpected token and try again.
-	 * @see Jsoner#deserialize(Reader)
-	 * @see StringReader */
-	public static Object deserialize(final String deserializable) throws DeserializationException{
-		Object returnable;
-		StringReader readableDeserializable = null;
-		try{
-			readableDeserializable = new StringReader(deserializable);
-			returnable = Jsoner.deserialize(readableDeserializable);
-		}catch(IOException | NullPointerException caught){
-			/* They both have the same recovery scenario.
-			 * See StringReader.
-			 * If deserializable is null, it should be reasonable to expect null back. */
-			returnable = null;
-		}finally{
-			if(readableDeserializable != null){
-				readableDeserializable.close();
-			}
-		}
-		return returnable;
-	}
+    /**
+     * A convenience method that assumes a StringReader to deserialize a string.
+     * 
+     * @param deserializable representing content to be deserialized as JSON.
+     * @return either a boolean, null, Number, String, JsonObject, or JsonArray
+     *         that best represents the deserializable.
+     * @throws DeserializationException if an unexpected token is encountered in
+     *             the deserializable. To recover from a
+     *             DeserializationException: fix the deserializable to no longer
+     *             have an unexpected token and try again.
+     * @see Jsoner#deserialize(Reader)
+     * @see StringReader
+     */
+    public static Object deserialize(final String deserializable) throws DeserializationException {
+        Object returnable;
+        StringReader readableDeserializable = null;
+        try {
+            readableDeserializable = new StringReader(deserializable);
+            returnable = Jsoner.deserialize(readableDeserializable);
+        } catch (IOException | NullPointerException caught) {
+            /*
+             * They both have the same recovery scenario. See StringReader. If
+             * deserializable is null, it should be reasonable to expect null
+             * back.
+             */
+            returnable = null;
+        } finally {
+            if (readableDeserializable != null) {
+                readableDeserializable.close();
+            }
+        }
+        return returnable;
+    }
 
-	/** A convenience method that assumes a JsonArray must be deserialized.
-	 * @param deserializable representing content to be deserializable as a JsonArray.
-	 * @param defaultValue representing what would be returned if deserializable isn't a JsonArray or an IOException,
-	 *        NullPointerException, or DeserializationException occurs during deserialization.
-	 * @return a JsonArray that represents the deserializable, or the defaultValue if there isn't a JsonArray that
-	 *         represents deserializable.
-	 * @see Jsoner#deserialize(Reader) */
-	public static JsonArray deserialize(final String deserializable, final JsonArray defaultValue){
-		StringReader readable = null;
-		JsonArray returnable;
-		try{
-			readable = new StringReader(deserializable);
-			returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS)).<JsonArray> getCollection(0);
-		}catch(NullPointerException | IOException | DeserializationException caught){
-			/* Don't care, just return the default value. */
-			returnable = defaultValue;
-		}finally{
-			if(readable != null){
-				readable.close();
-			}
-		}
-		return returnable;
-	}
+    /**
+     * A convenience method that assumes a JsonArray must be deserialized.
+     * 
+     * @param deserializable representing content to be deserializable as a
+     *            JsonArray.
+     * @param defaultValue representing what would be returned if deserializable
+     *            isn't a JsonArray or an IOException, NullPointerException, or
+     *            DeserializationException occurs during deserialization.
+     * @return a JsonArray that represents the deserializable, or the
+     *         defaultValue if there isn't a JsonArray that represents
+     *         deserializable.
+     * @see Jsoner#deserialize(Reader)
+     */
+    public static JsonArray deserialize(final String deserializable, final JsonArray defaultValue) {
+        StringReader readable = null;
+        JsonArray returnable;
+        try {
+            readable = new StringReader(deserializable);
+            returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS)).<JsonArray> getCollection(0);
+        } catch (NullPointerException | IOException | DeserializationException caught) {
+            /* Don't care, just return the default value. */
+            returnable = defaultValue;
+        } finally {
+            if (readable != null) {
+                readable.close();
+            }
+        }
+        return returnable;
+    }
 
-	/** A convenience method that assumes a JsonObject must be deserialized.
-	 * @param deserializable representing content to be deserializable as a JsonObject.
-	 * @param defaultValue representing what would be returned if deserializable isn't a JsonObject or an IOException,
-	 *        NullPointerException, or DeserializationException occurs during deserialization.
-	 * @return a JsonObject that represents the deserializable, or the defaultValue if there isn't a JsonObject that
-	 *         represents deserializable.
-	 * @see Jsoner#deserialize(Reader) */
-	public static JsonObject deserialize(final String deserializable, final JsonObject defaultValue){
-		StringReader readable = null;
-		JsonObject returnable;
-		try{
-			readable = new StringReader(deserializable);
-			returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_OBJECTS)).<JsonObject> getMap(0);
-		}catch(NullPointerException | IOException | DeserializationException caught){
-			/* Don't care, just return the default value. */
-			returnable = defaultValue;
-		}finally{
-			if(readable != null){
-				readable.close();
-			}
-		}
-		return returnable;
-	}
+    /**
+     * A convenience method that assumes a JsonObject must be deserialized.
+     * 
+     * @param deserializable representing content to be deserializable as a
+     *            JsonObject.
+     * @param defaultValue representing what would be returned if deserializable
+     *            isn't a JsonObject or an IOException, NullPointerException, or
+     *            DeserializationException occurs during deserialization.
+     * @return a JsonObject that represents the deserializable, or the
+     *         defaultValue if there isn't a JsonObject that represents
+     *         deserializable.
+     * @see Jsoner#deserialize(Reader)
+     */
+    public static JsonObject deserialize(final String deserializable, final JsonObject defaultValue) {
+        StringReader readable = null;
+        JsonObject returnable;
+        try {
+            readable = new StringReader(deserializable);
+            returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_OBJECTS)).<JsonObject> getMap(0);
+        } catch (NullPointerException | IOException | DeserializationException caught) {
+            /* Don't care, just return the default value. */
+            returnable = defaultValue;
+        } finally {
+            if (readable != null) {
+                readable.close();
+            }
+        }
+        return returnable;
+    }
 
-	/** A convenience method that assumes multiple RFC 4627 JSON values (except numbers) have been concatenated together
-	 * for deserilization which will be collectively returned in a JsonArray wrapper.
-	 * There may be numbers included, they just must not be concatenated together as it is prone to
-	 * NumberFormatExceptions (thus causing a DeserializationException) or the numbers no longer represent their
-	 * respective values.
-	 * Examples:
-	 * "123null321" returns [123, null, 321]
-	 * "nullnullnulltruefalse\"\"{}[]" returns [null, null, null, true, false, "", {}, []]
-	 * "123" appended to "321" returns [123321]
-	 * "12.3" appended to "3.21" throws DeserializationException(NumberFormatException)
-	 * "123" appended to "-321" throws DeserializationException(NumberFormatException)
-	 * "123e321" appended to "-1" throws DeserializationException(NumberFormatException)
-	 * "null12.33.21null" throws DeserializationException(NumberFormatException)
-	 * @param deserializable representing concatenated content to be deserialized as JSON in one reader. Its contents
-	 *        may
-	 *        not contain two numbers concatenated together.
-	 * @return a JsonArray that contains each of the concatenated objects as its elements. Each concatenated element is
-	 *         either a boolean, null, Number, String, JsonArray, or JsonObject that best represents the concatenated
-	 *         content inside deserializable.
-	 * @throws DeserializationException if an unexpected token is encountered in the deserializable. To recover from a
-	 *         DeserializationException: fix the deserializable to no longer have an unexpected token and try again.
-	 * @throws IOException when the underlying reader encounters an I/O error. Ensure the reader is properly
-	 *         instantiated, isn't closed, or that it is ready before trying again. */
-	public static JsonArray deserializeMany(final Reader deserializable) throws DeserializationException, IOException{
-		return Jsoner.deserialize(deserializable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS, DeserializationOptions.ALLOW_JSON_OBJECTS, DeserializationOptions.ALLOW_JSON_DATA, DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES));
-	}
+    /**
+     * A convenience method that assumes multiple RFC 4627 JSON values (except
+     * numbers) have been concatenated together for deserilization which will be
+     * collectively returned in a JsonArray wrapper. There may be numbers
+     * included, they just must not be concatenated together as it is prone to
+     * NumberFormatExceptions (thus causing a DeserializationException) or the
+     * numbers no longer represent their respective values. Examples:
+     * "123null321" returns [123, null, 321] "nullnullnulltruefalse\"\"{}[]"
+     * returns [null, null, null, true, false, "", {}, []] "123" appended to
+     * "321" returns [123321] "12.3" appended to "3.21" throws
+     * DeserializationException(NumberFormatException) "123" appended to "-321"
+     * throws DeserializationException(NumberFormatException) "123e321" appended
+     * to "-1" throws DeserializationException(NumberFormatException)
+     * "null12.33.21null" throws DeserializationException(NumberFormatException)
+     * 
+     * @param deserializable representing concatenated content to be
+     *            deserialized as JSON in one reader. Its contents may not
+     *            contain two numbers concatenated together.
+     * @return a JsonArray that contains each of the concatenated objects as its
+     *         elements. Each concatenated element is either a boolean, null,
+     *         Number, String, JsonArray, or JsonObject that best represents the
+     *         concatenated content inside deserializable.
+     * @throws DeserializationException if an unexpected token is encountered in
+     *             the deserializable. To recover from a
+     *             DeserializationException: fix the deserializable to no longer
+     *             have an unexpected token and try again.
+     * @throws IOException when the underlying reader encounters an I/O error.
+     *             Ensure the reader is properly instantiated, isn't closed, or
+     *             that it is ready before trying again.
+     */
+    public static JsonArray deserializeMany(final Reader deserializable) throws DeserializationException, IOException {
+        return Jsoner.deserialize(deserializable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS, DeserializationOptions.ALLOW_JSON_OBJECTS,
+                                                             DeserializationOptions.ALLOW_JSON_DATA, DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES));
+    }
 
-	/** Escapes potentially confusing or important characters in the String provided.
-	 * @param escapable an unescaped string.
-	 * @return an escaped string for usage in JSON; An escaped string is one that has escaped all of the quotes ("),
-	 *         backslashes (\), return character (\r), new line character (\n), tab character (\t),
-	 *         backspace character (\b), form feed character (\f) and other control characters [u0000..u001F] or
-	 *         characters [u007F..u009F], [u2000..u20FF] with a
-	 *         backslash (\) which itself must be escaped by the backslash in a java string. */
-	public static String escape(final String escapable){
-		final StringBuilder builder = new StringBuilder();
-		final int characters = escapable.length();
-		for(int i = 0; i < characters; i++){
-			final char character = escapable.charAt(i);
-			switch(character){
-				case '"':
-					builder.append("\\\"");
-					break;
-				case '\\':
-					builder.append("\\\\");
-					break;
-				case '\b':
-					builder.append("\\b");
-					break;
-				case '\f':
-					builder.append("\\f");
-					break;
-				case '\n':
-					builder.append("\\n");
-					break;
-				case '\r':
-					builder.append("\\r");
-					break;
-				case '\t':
-					builder.append("\\t");
-					break;
-				case '/':
-					builder.append("\\/");
-					break;
-				default:
-					/* The many characters that get replaced are benign to software but could be mistaken by people
-					 * reading it for a JSON relevant character. */
-					if(((character >= '\u0000') && (character <= '\u001F')) || ((character >= '\u007F') && (character <= '\u009F')) || ((character >= '\u2000') && (character <= '\u20FF'))){
-						final String characterHexCode = Integer.toHexString(character);
-						builder.append("\\u");
-						for(int k = 0; k < (4 - characterHexCode.length()); k++){
-							builder.append("0");
-						}
-						builder.append(characterHexCode.toUpperCase());
-					}else{
-						/* Character didn't need escaping. */
-						builder.append(character);
-					}
-			}
-		}
-		return builder.toString();
-	}
+    /**
+     * Escapes potentially confusing or important characters in the String
+     * provided.
+     * 
+     * @param escapable an unescaped string.
+     * @return an escaped string for usage in JSON; An escaped string is one
+     *         that has escaped all of the quotes ("), backslashes (\), return
+     *         character (\r), new line character (\n), tab character (\t),
+     *         backspace character (\b), form feed character (\f) and other
+     *         control characters [u0000..u001F] or characters [u007F..u009F],
+     *         [u2000..u20FF] with a backslash (\) which itself must be escaped
+     *         by the backslash in a java string.
+     */
+    public static String escape(final String escapable) {
+        final StringBuilder builder = new StringBuilder();
+        final int characters = escapable.length();
+        for (int i = 0; i < characters; i++) {
+            final char character = escapable.charAt(i);
+            switch (character) {
+            case '"':
+                builder.append("\\\"");
+                break;
+            case '\\':
+                builder.append("\\\\");
+                break;
+            case '\b':
+                builder.append("\\b");
+                break;
+            case '\f':
+                builder.append("\\f");
+                break;
+            case '\n':
+                builder.append("\\n");
+                break;
+            case '\r':
+                builder.append("\\r");
+                break;
+            case '\t':
+                builder.append("\\t");
+                break;
+            case '/':
+                builder.append("\\/");
+                break;
+            default:
+                /*
+                 * The many characters that get replaced are benign to software
+                 * but could be mistaken by people reading it for a JSON
+                 * relevant character.
+                 */
+                if (((character >= '\u0000') && (character <= '\u001F')) || ((character >= '\u007F') && (character <= '\u009F'))
+                    || ((character >= '\u2000') && (character <= '\u20FF'))) {
+                    final String characterHexCode = Integer.toHexString(character);
+                    builder.append("\\u");
+                    for (int k = 0; k < (4 - characterHexCode.length()); k++) {
+                        builder.append("0");
+                    }
+                    builder.append(characterHexCode.toUpperCase());
+                } else {
+                    /* Character didn't need escaping. */
+                    builder.append(character);
+                }
+            }
+        }
+        return builder.toString();
+    }
 
-	/** Processes the lexer's reader for the next token.
-	 * @param lexer represents a text processor being used in the deserialization process.
-	 * @return a token representing a meaningful element encountered by the lexer.
-	 * @throws DeserializationException if an unexpected character is encountered while processing the text.
-	 * @throws IOException if the underlying reader inside the lexer encounters an I/O problem, like being prematurely
-	 *         closed. */
-	private static Yytoken lexNextToken(final Yylex lexer) throws DeserializationException, IOException{
-		Yytoken returnable;
-		/* Parse through the next token. */
-		returnable = lexer.yylex();
-		if(returnable == null){
-			/* If there isn't another token, it must be the end. */
-			returnable = new Yytoken(Yytoken.Types.END, null);
-		}
-		return returnable;
-	}
+    /**
+     * Processes the lexer's reader for the next token.
+     * 
+     * @param lexer represents a text processor being used in the
+     *            deserialization process.
+     * @return a token representing a meaningful element encountered by the
+     *         lexer.
+     * @throws DeserializationException if an unexpected character is
+     *             encountered while processing the text.
+     * @throws IOException if the underlying reader inside the lexer encounters
+     *             an I/O problem, like being prematurely closed.
+     */
+    private static Yytoken lexNextToken(final Yylex lexer) throws DeserializationException, IOException {
+        Yytoken returnable;
+        /* Parse through the next token. */
+        returnable = lexer.yylex();
+        if (returnable == null) {
+            /* If there isn't another token, it must be the end. */
+            returnable = new Yytoken(Yytoken.Types.END, null);
+        }
+        return returnable;
+    }
 
-	/** Used for state transitions while deserializing.
-	 * @param stateStack represents the deserialization states saved for future processing.
-	 * @return a state for deserialization context so it knows how to consume the next token. */
-	private static States popNextState(final LinkedList<States> stateStack){
-		if(stateStack.size() > 0){
-			return stateStack.removeLast();
-		}else{
-			return States.PARSED_ERROR;
-		}
-	}
+    /**
+     * Used for state transitions while deserializing.
+     * 
+     * @param stateStack represents the deserialization states saved for future
+     *            processing.
+     * @return a state for deserialization context so it knows how to consume
+     *         the next token.
+     */
+    private static States popNextState(final LinkedList<States> stateStack) {
+        if (stateStack.size() > 0) {
+            return stateStack.removeLast();
+        } else {
+            return States.PARSED_ERROR;
+        }
+    }
 
-	/** Formats the JSON string to be more easily human readable using tabs for indentation.
-	 * @param printable representing a JSON formatted string with out extraneous characters, like one returned from
-	 *        Jsoner#serialize(Object).
-	 * @return printable except it will have '\n' then '\t' characters inserted after '[', '{', ',' and before ']' '}'
-	 *         tokens in the JSON. It will return null if printable isn't a JSON string. */
-	public static String prettyPrint(final String printable){
-		return Jsoner.prettyPrint(printable, "\t");
-	}
+    /**
+     * Formats the JSON string to be more easily human readable using tabs for
+     * indentation.
+     * 
+     * @param printable representing a JSON formatted string with out extraneous
+     *            characters, like one returned from Jsoner#serialize(Object).
+     * @return printable except it will have '\n' then '\t' characters inserted
+     *         after '[', '{', ',' and before ']' '}' tokens in the JSON. It
+     *         will return null if printable isn't a JSON string.
+     */
+    public static String prettyPrint(final String printable) {
+        return Jsoner.prettyPrint(printable, "\t");
+    }
 
-	/** Formats the JSON string to be more easily human readable using an arbitrary amount of spaces for indentation.
-	 * @param printable representing a JSON formatted string with out extraneous characters, like one returned from
-	 *        Jsoner#serialize(Object).
-	 * @param spaces representing the amount of spaces to use for indentation. Must be between 2 and 10.
-	 * @return printable except it will have '\n' then space characters inserted after '[', '{', ',' and before ']' '}'
-	 *         tokens in the JSON. It will return null if printable isn't a JSON string.
-	 * @throws IllegalArgumentException if spaces isn't between [2..10].
-	 * @see Jsoner#prettyPrint(String)
-	 * @since 2.2.0 to allow pretty printing with spaces instead of tabs. */
-	public static String prettyPrint(final String printable, final int spaces){
-		if((spaces > 10) || (spaces < 2)){
-			throw new IllegalArgumentException("Indentation with spaces must be between 2 and 10.");
-		}
-		final StringBuilder indentation = new StringBuilder("");
-		for(int i = 0; i < spaces; i++){
-			indentation.append(" ");
-		}
-		return Jsoner.prettyPrint(printable, indentation.toString());
-	}
+    /**
+     * Formats the JSON string to be more easily human readable using an
+     * arbitrary amount of spaces for indentation.
+     * 
+     * @param printable representing a JSON formatted string with out extraneous
+     *            characters, like one returned from Jsoner#serialize(Object).
+     * @param spaces representing the amount of spaces to use for indentation.
+     *            Must be between 2 and 10.
+     * @return printable except it will have '\n' then space characters inserted
+     *         after '[', '{', ',' and before ']' '}' tokens in the JSON. It
+     *         will return null if printable isn't a JSON string.
+     * @throws IllegalArgumentException if spaces isn't between [2..10].
+     * @see Jsoner#prettyPrint(String)
+     * @since 2.2.0 to allow pretty printing with spaces instead of tabs.
+     */
+    public static String prettyPrint(final String printable, final int spaces) {
+        if ((spaces > 10) || (spaces < 2)) {
+            throw new IllegalArgumentException("Indentation with spaces must be between 2 and 10.");
+        }
+        final StringBuilder indentation = new StringBuilder("");
+        for (int i = 0; i < spaces; i++) {
+            indentation.append(" ");
+        }
+        return Jsoner.prettyPrint(printable, indentation.toString());
+    }
 
-	/** Makes the JSON string more easily human readable using indentation of the caller's choice.
-	 * @param printable representing a JSON formatted string with out extraneous characters, like one returned from
-	 *        Jsoner#serialize(Object).
-	 * @param indentation representing the indentation used to format the JSON string.
-	 * @return printable except it will have '\n' then indentation characters inserted after '[', '{', ',' and before
-	 *         ']' '}'
-	 *         tokens in the JSON. It will return null if printable isn't a JSON string. */
-	private static String prettyPrint(final String printable, final String indentation){
-		final Yylex lexer = new Yylex(new StringReader(printable));
-		Yytoken lexed;
-		final StringBuilder returnable = new StringBuilder();
-		int level = 0;
-		try{
-			do{
-				lexed = Jsoner.lexNextToken(lexer);
-				switch(lexed.getType()){
-					case COLON:
-						returnable.append(":");
-						break;
-					case COMMA:
-						returnable.append(lexed.getValue());
-						returnable.append("\n");
-						for(int i = 0; i < level; i++){
-							returnable.append(indentation);
-						}
-						break;
-					case END:
-						break;
-					case LEFT_BRACE:
-					case LEFT_SQUARE:
-						returnable.append(lexed.getValue());
-						returnable.append("\n");
-						level++;
-						for(int i = 0; i < level; i++){
-							returnable.append(indentation);
-						}
-						break;
-					case RIGHT_BRACE:
-					case RIGHT_SQUARE:
-						returnable.append("\n");
-						level--;
-						for(int i = 0; i < level; i++){
-							returnable.append(indentation);
-						}
-						returnable.append(lexed.getValue());
-						break;
-					default:
-						if(lexed.getValue() instanceof String){
-							returnable.append("\"");
-							returnable.append(Jsoner.escape((String)lexed.getValue()));
-							returnable.append("\"");
-						}else{
-							returnable.append(lexed.getValue());
-						}
-						break;
-				}
-				//System.out.println(lexed);
-			}while(!lexed.getType().equals(Yytoken.Types.END));
-		}catch(final DeserializationException caught){
-			/* This is according to the method's contract. */
-			return null;
-		}catch(final IOException caught){
-			/* See StringReader. */
-			return null;
-		}
-		//System.out.println(printable);
-		//System.out.println(returnable);
-		//System.out.println(Jsoner.escape(returnable.toString()));
-		return returnable.toString();
-	}
+    /**
+     * Makes the JSON string more easily human readable using indentation of the
+     * caller's choice.
+     * 
+     * @param printable representing a JSON formatted string with out extraneous
+     *            characters, like one returned from Jsoner#serialize(Object).
+     * @param indentation representing the indentation used to format the JSON
+     *            string.
+     * @return printable except it will have '\n' then indentation characters
+     *         inserted after '[', '{', ',' and before ']' '}' tokens in the
+     *         JSON. It will return null if printable isn't a JSON string.
+     */
+    private static String prettyPrint(final String printable, final String indentation) {
+        final Yylex lexer = new Yylex(new StringReader(printable));
+        Yytoken lexed;
+        final StringBuilder returnable = new StringBuilder();
+        int level = 0;
+        try {
+            do {
+                lexed = Jsoner.lexNextToken(lexer);
+                switch (lexed.getType()) {
+                case COLON:
+                    returnable.append(":");
+                    break;
+                case COMMA:
+                    returnable.append(lexed.getValue());
+                    returnable.append("\n");
+                    for (int i = 0; i < level; i++) {
+                        returnable.append(indentation);
+                    }
+                    break;
+                case END:
+                    break;
+                case LEFT_BRACE:
+                case LEFT_SQUARE:
+                    returnable.append(lexed.getValue());
+                    returnable.append("\n");
+                    level++;
+                    for (int i = 0; i < level; i++) {
+                        returnable.append(indentation);
+                    }
+                    break;
+                case RIGHT_BRACE:
+                case RIGHT_SQUARE:
+                    returnable.append("\n");
+                    level--;
+                    for (int i = 0; i < level; i++) {
+                        returnable.append(indentation);
+                    }
+                    returnable.append(lexed.getValue());
+                    break;
+                default:
+                    if (lexed.getValue() instanceof String) {
+                        returnable.append("\"");
+                        returnable.append(Jsoner.escape((String)lexed.getValue()));
+                        returnable.append("\"");
+                    } else {
+                        returnable.append(lexed.getValue());
+                    }
+                    break;
+                }
+                // System.out.println(lexed);
+            } while (!lexed.getType().equals(Yytoken.Types.END));
+        } catch (final DeserializationException caught) {
+            /* This is according to the method's contract. */
+            return null;
+        } catch (final IOException caught) {
+            /* See StringReader. */
+            return null;
+        }
+        // System.out.println(printable);
+        // System.out.println(returnable);
+        // System.out.println(Jsoner.escape(returnable.toString()));
+        return returnable.toString();
+    }
 
-	/** A convenience method that assumes a StringWriter.
-	 * @param jsonSerializable represents the object that should be serialized as a string in JSON format.
-	 * @return a string, in JSON format, that represents the object provided.
-	 * @throws IllegalArgumentException if the jsonSerializable isn't serializable in JSON.
-	 * @see Jsoner#serialize(Object, Writer)
-	 * @see StringWriter */
-	public static String serialize(final Object jsonSerializable){
-		final StringWriter writableDestination = new StringWriter();
-		try{
-			Jsoner.serialize(jsonSerializable, writableDestination);
-		}catch(final IOException caught){
-			/* See StringWriter. */
-		}
-		return writableDestination.toString();
-	}
+    /**
+     * A convenience method that assumes a StringWriter.
+     * 
+     * @param jsonSerializable represents the object that should be serialized
+     *            as a string in JSON format.
+     * @return a string, in JSON format, that represents the object provided.
+     * @throws IllegalArgumentException if the jsonSerializable isn't
+     *             serializable in JSON.
+     * @see Jsoner#serialize(Object, Writer)
+     * @see StringWriter
+     */
+    public static String serialize(final Object jsonSerializable) {
+        final StringWriter writableDestination = new StringWriter();
+        try {
+            Jsoner.serialize(jsonSerializable, writableDestination);
+        } catch (final IOException caught) {
+            /* See StringWriter. */
+        }
+        return writableDestination.toString();
+    }
 
-	/** Serializes values according to the RFC 4627 JSON specification. It will also trust the serialization provided by
-	 * any Jsonables it serializes and serializes Enums that don't implement Jsonable as a string of their fully
-	 * qualified name.
-	 * @param jsonSerializable represents the object that should be serialized in JSON format.
-	 * @param writableDestination represents where the resulting JSON text is written to.
-	 * @throws IOException if the writableDestination encounters an I/O problem, like being closed while in use.
-	 * @throws IllegalArgumentException if the jsonSerializable isn't serializable in JSON. */
-	public static void serialize(final Object jsonSerializable, final Writer writableDestination) throws IOException{
-		Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.of(SerializationOptions.ALLOW_JSONABLES, SerializationOptions.ALLOW_FULLY_QUALIFIED_ENUMERATIONS));
-	}
+    /**
+     * Serializes values according to the RFC 4627 JSON specification. It will
+     * also trust the serialization provided by any Jsonables it serializes and
+     * serializes Enums that don't implement Jsonable as a string of their fully
+     * qualified name.
+     * 
+     * @param jsonSerializable represents the object that should be serialized
+     *            in JSON format.
+     * @param writableDestination represents where the resulting JSON text is
+     *            written to.
+     * @throws IOException if the writableDestination encounters an I/O problem,
+     *             like being closed while in use.
+     * @throws IllegalArgumentException if the jsonSerializable isn't
+     *             serializable in JSON.
+     */
+    public static void serialize(final Object jsonSerializable, final Writer writableDestination) throws IOException {
+        Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.of(SerializationOptions.ALLOW_JSONABLES, SerializationOptions.ALLOW_FULLY_QUALIFIED_ENUMERATIONS));
+    }
 
-	/** Serialize values to JSON and write them to the provided writer based on behavior flags.
-	 * @param jsonSerializable represents the object that should be serialized to a string in JSON format.
-	 * @param writableDestination represents where the resulting JSON text is written to.
-	 * @param replacement represents what is serialized instead of a non-JSON value when replacements are allowed.
-	 * @param flags represents the allowances and restrictions on serialization.
-	 * @throws IOException if the writableDestination encounters an I/O problem.
-	 * @throws IllegalArgumentException if the jsonSerializable isn't serializable in JSON.
-	 * @see SerializationOptions */
-	private static void serialize(final Object jsonSerializable, final Writer writableDestination, final Set<SerializationOptions> flags) throws IOException{
-		if(jsonSerializable == null){
-			/* When a null is passed in the word null is supported in JSON. */
-			writableDestination.write("null");
-		}else if(((jsonSerializable instanceof Jsonable) && flags.contains(SerializationOptions.ALLOW_JSONABLES))){
-			/* Writes the writable as defined by the writable. */
-			writableDestination.write(((Jsonable)jsonSerializable).toJson());
-		}else if((jsonSerializable instanceof Enum) && flags.contains(SerializationOptions.ALLOW_FULLY_QUALIFIED_ENUMERATIONS)){
-			/* Writes the enum as a special case of string. All enums (unless they implement Jsonable) will be the
-			 * string literal "${DECLARING_CLASS_NAME}.${ENUM_NAME}" as their value. */
-			@SuppressWarnings("rawtypes")
-			final Enum e = (Enum)jsonSerializable;
-			writableDestination.write('"');
-			writableDestination.write(e.getDeclaringClass().getName());
-			writableDestination.write('.');
-			writableDestination.write(e.name());
-			writableDestination.write('"');
-		}else if(jsonSerializable instanceof String){
-			/* Make sure the string is properly escaped. */
-			writableDestination.write('"');
-			writableDestination.write(Jsoner.escape((String)jsonSerializable));
-			writableDestination.write('"');
-		}else if(jsonSerializable instanceof Double){
-			if(((Double)jsonSerializable).isInfinite() || ((Double)jsonSerializable).isNaN()){
-				/* Infinite and not a number are not supported by the JSON specification, so null is used instead. */
-				writableDestination.write("null");
-			}else{
-				writableDestination.write(jsonSerializable.toString());
-			}
-		}else if(jsonSerializable instanceof Float){
-			if(((Float)jsonSerializable).isInfinite() || ((Float)jsonSerializable).isNaN()){
-				/* Infinite and not a number are not supported by the JSON specification, so null is used instead. */
-				writableDestination.write("null");
-			}else{
-				writableDestination.write(jsonSerializable.toString());
-			}
-		}else if(jsonSerializable instanceof Number){
-			writableDestination.write(jsonSerializable.toString());
-		}else if(jsonSerializable instanceof Boolean){
-			writableDestination.write(jsonSerializable.toString());
-		}else if(jsonSerializable instanceof Map){
-			/* Writes the map in JSON object format. */
-			boolean isFirstEntry = true;
-			@SuppressWarnings("rawtypes")
-			final Iterator entries = ((Map)jsonSerializable).entrySet().iterator();
-			writableDestination.write('{');
-			while(entries.hasNext()){
-				if(isFirstEntry){
-					isFirstEntry = false;
-				}else{
-					writableDestination.write(',');
-				}
-				@SuppressWarnings("rawtypes")
-				final Map.Entry entry = (Map.Entry)entries.next();
-				Jsoner.serialize(entry.getKey(), writableDestination, flags);
-				writableDestination.write(':');
-				Jsoner.serialize(entry.getValue(), writableDestination, flags);
-			}
-			writableDestination.write('}');
-		}else if(jsonSerializable instanceof Collection){
-			/* Writes the collection in JSON array format. */
-			boolean isFirstElement = true;
-			@SuppressWarnings("rawtypes")
-			final Iterator elements = ((Collection)jsonSerializable).iterator();
-			writableDestination.write('[');
-			while(elements.hasNext()){
-				if(isFirstElement){
-					isFirstElement = false;
-				}else{
-					writableDestination.write(',');
-				}
-				Jsoner.serialize(elements.next(), writableDestination, flags);
-			}
-			writableDestination.write(']');
-		}else if(jsonSerializable instanceof byte[]){
-			/* Writes the array in JSON array format. */
-			final byte[] writableArray = (byte[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write('[');
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write(',');
-				}
-			}
-			writableDestination.write(']');
-		}else if(jsonSerializable instanceof short[]){
-			/* Writes the array in JSON array format. */
-			final short[] writableArray = (short[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write('[');
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write(',');
-				}
-			}
-			writableDestination.write(']');
-		}else if(jsonSerializable instanceof int[]){
-			/* Writes the array in JSON array format. */
-			final int[] writableArray = (int[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write('[');
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write(',');
-				}
-			}
-			writableDestination.write(']');
-		}else if(jsonSerializable instanceof long[]){
-			/* Writes the array in JSON array format. */
-			final long[] writableArray = (long[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write('[');
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write(',');
-				}
-			}
-			writableDestination.write(']');
-		}else if(jsonSerializable instanceof float[]){
-			/* Writes the array in JSON array format. */
-			final float[] writableArray = (float[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write('[');
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write(',');
-				}
-			}
-			writableDestination.write(']');
-		}else if(jsonSerializable instanceof double[]){
-			/* Writes the array in JSON array format. */
-			final double[] writableArray = (double[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write('[');
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write(',');
-				}
-			}
-			writableDestination.write(']');
-		}else if(jsonSerializable instanceof boolean[]){
-			/* Writes the array in JSON array format. */
-			final boolean[] writableArray = (boolean[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write('[');
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write(',');
-				}
-			}
-			writableDestination.write(']');
-		}else if(jsonSerializable instanceof char[]){
-			/* Writes the array in JSON array format. */
-			final char[] writableArray = (char[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write("[\"");
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write("\",\"");
-				}
-			}
-			writableDestination.write("\"]");
-		}else if(jsonSerializable instanceof Object[]){
-			/* Writes the array in JSON array format. */
-			final Object[] writableArray = (Object[])jsonSerializable;
-			final int numberOfElements = writableArray.length;
-			writableDestination.write('[');
-			for(int i = 1; i <= numberOfElements; i++){
-				if(i == numberOfElements){
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-				}else{
-					Jsoner.serialize(writableArray[i], writableDestination, flags);
-					writableDestination.write(",");
-				}
-			}
-			writableDestination.write(']');
-		}else{
-			/* TODO a potential feature for future release since POJOs are often represented as JsonObjects. It would be
-			 * nice to have a flag that tries to reflectively figure out what a non-Jsonable POJO's fields are and use
-			 * their names as keys and their respective values for the keys' values in the JsonObject?
-			 * Naturally implementing Jsonable is safer and in many ways makes this feature a convenience for not
-			 * needing
-			 * to implement Jsonable for very simple POJOs.
-			 * If it fails to produce a JsonObject to serialize it should defer to replacements if allowed.
-			 * If replacement fails it should defer to invalids if allowed.
-			 * This feature would require another serialize method exposed to allow this serialization.
-			 * This feature (although perhaps useful on its own) would also include a method in the JsonObject where you
-			 * pass it a class and it would do its best to instantiate a POJO of the class using the keys in the
-			 * JsonObject. */
-			/* It cannot by any measure be safely serialized according to specification. */
-			if(flags.contains(SerializationOptions.ALLOW_INVALIDS)){
-				/* Can be helpful for debugging how it isn't valid. */
-				writableDestination.write(jsonSerializable.toString());
-			}else{
-				/* Notify the caller the cause of failure for the serialization. */
-				throw new IllegalArgumentException("Encountered a: " + jsonSerializable.getClass().getName() + " as: " + jsonSerializable.toString() + "  that isn't JSON serializable.\n  Try:\n    1) Implementing the Jsonable interface for the object to return valid JSON. If it already does it probably has a bug.\n    2) If you cannot edit the source of the object or couple it with this library consider wrapping it in a class that does implement the Jsonable interface.\n    3) Otherwise convert it t [...]
-			}
-		}
-		//System.out.println(writableDestination.toString());
-	}
+    /**
+     * Serialize values to JSON and write them to the provided writer based on
+     * behavior flags.
+     * 
+     * @param jsonSerializable represents the object that should be serialized
+     *            to a string in JSON format.
+     * @param writableDestination represents where the resulting JSON text is
+     *            written to.
+     * @param replacement represents what is serialized instead of a non-JSON
+     *            value when replacements are allowed.
+     * @param flags represents the allowances and restrictions on serialization.
+     * @throws IOException if the writableDestination encounters an I/O problem.
+     * @throws IllegalArgumentException if the jsonSerializable isn't
+     *             serializable in JSON.
+     * @see SerializationOptions
+     */
+    private static void serialize(final Object jsonSerializable, final Writer writableDestination, final Set<SerializationOptions> flags) throws IOException {
+        if (jsonSerializable == null) {
+            /* When a null is passed in the word null is supported in JSON. */
+            writableDestination.write("null");
+        } else if (((jsonSerializable instanceof Jsonable) && flags.contains(SerializationOptions.ALLOW_JSONABLES))) {
+            /* Writes the writable as defined by the writable. */
+            writableDestination.write(((Jsonable)jsonSerializable).toJson());
+        } else if ((jsonSerializable instanceof Enum) && flags.contains(SerializationOptions.ALLOW_FULLY_QUALIFIED_ENUMERATIONS)) {
+            /*
+             * Writes the enum as a special case of string. All enums (unless
+             * they implement Jsonable) will be the string literal
+             * "${DECLARING_CLASS_NAME}.${ENUM_NAME}" as their value.
+             */
+            @SuppressWarnings("rawtypes")
+            final Enum e = (Enum)jsonSerializable;
+            writableDestination.write('"');
+            writableDestination.write(e.getDeclaringClass().getName());
+            writableDestination.write('.');
+            writableDestination.write(e.name());
+            writableDestination.write('"');
+        } else if (jsonSerializable instanceof String) {
+            /* Make sure the string is properly escaped. */
+            writableDestination.write('"');
+            writableDestination.write(Jsoner.escape((String)jsonSerializable));
+            writableDestination.write('"');
+        } else if (jsonSerializable instanceof Double) {
+            if (((Double)jsonSerializable).isInfinite() || ((Double)jsonSerializable).isNaN()) {
+                /*
+                 * Infinite and not a number are not supported by the JSON
+                 * specification, so null is used instead.
+                 */
+                writableDestination.write("null");
+            } else {
+                writableDestination.write(jsonSerializable.toString());
+            }
+        } else if (jsonSerializable instanceof Float) {
+            if (((Float)jsonSerializable).isInfinite() || ((Float)jsonSerializable).isNaN()) {
+                /*
+                 * Infinite and not a number are not supported by the JSON
+                 * specification, so null is used instead.
+                 */
+                writableDestination.write("null");
+            } else {
+                writableDestination.write(jsonSerializable.toString());
+            }
+        } else if (jsonSerializable instanceof Number) {
+            writableDestination.write(jsonSerializable.toString());
+        } else if (jsonSerializable instanceof Boolean) {
+            writableDestination.write(jsonSerializable.toString());
+        } else if (jsonSerializable instanceof Map) {
+            /* Writes the map in JSON object format. */
+            boolean isFirstEntry = true;
+            @SuppressWarnings("rawtypes")
+            final Iterator entries = ((Map)jsonSerializable).entrySet().iterator();
+            writableDestination.write('{');
+            while (entries.hasNext()) {
+                if (isFirstEntry) {
+                    isFirstEntry = false;
+                } else {
+                    writableDestination.write(',');
+                }
+                @SuppressWarnings("rawtypes")
+                final Map.Entry entry = (Map.Entry)entries.next();
+                Jsoner.serialize(entry.getKey(), writableDestination, flags);
+                writableDestination.write(':');
+                Jsoner.serialize(entry.getValue(), writableDestination, flags);
+            }
+            writableDestination.write('}');
+        } else if (jsonSerializable instanceof Collection) {
+            /* Writes the collection in JSON array format. */
+            boolean isFirstElement = true;
+            @SuppressWarnings("rawtypes")
+            final Iterator elements = ((Collection)jsonSerializable).iterator();
+            writableDestination.write('[');
+            while (elements.hasNext()) {
+                if (isFirstElement) {
+                    isFirstElement = false;
+                } else {
+                    writableDestination.write(',');
+                }
+                Jsoner.serialize(elements.next(), writableDestination, flags);
+            }
+            writableDestination.write(']');
+        } else if (jsonSerializable instanceof byte[]) {
+            /* Writes the array in JSON array format. */
+            final byte[] writableArray = (byte[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write('[');
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write(',');
+                }
+            }
+            writableDestination.write(']');
+        } else if (jsonSerializable instanceof short[]) {
+            /* Writes the array in JSON array format. */
+            final short[] writableArray = (short[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write('[');
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write(',');
+                }
+            }
+            writableDestination.write(']');
+        } else if (jsonSerializable instanceof int[]) {
+            /* Writes the array in JSON array format. */
+            final int[] writableArray = (int[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write('[');
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write(',');
+                }
+            }
+            writableDestination.write(']');
+        } else if (jsonSerializable instanceof long[]) {
+            /* Writes the array in JSON array format. */
+            final long[] writableArray = (long[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write('[');
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write(',');
+                }
+            }
+            writableDestination.write(']');
+        } else if (jsonSerializable instanceof float[]) {
+            /* Writes the array in JSON array format. */
+            final float[] writableArray = (float[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write('[');
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write(',');
+                }
+            }
+            writableDestination.write(']');
+        } else if (jsonSerializable instanceof double[]) {
+            /* Writes the array in JSON array format. */
+            final double[] writableArray = (double[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write('[');
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write(',');
+                }
+            }
+            writableDestination.write(']');
+        } else if (jsonSerializable instanceof boolean[]) {
+            /* Writes the array in JSON array format. */
+            final boolean[] writableArray = (boolean[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write('[');
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write(',');
+                }
+            }
+            writableDestination.write(']');
+        } else if (jsonSerializable instanceof char[]) {
+            /* Writes the array in JSON array format. */
+            final char[] writableArray = (char[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write("[\"");
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write("\",\"");
+                }
+            }
+            writableDestination.write("\"]");
+        } else if (jsonSerializable instanceof Object[]) {
+            /* Writes the array in JSON array format. */
+            final Object[] writableArray = (Object[])jsonSerializable;
+            final int numberOfElements = writableArray.length;
+            writableDestination.write('[');
+            for (int i = 1; i <= numberOfElements; i++) {
+                if (i == numberOfElements) {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                } else {
+                    Jsoner.serialize(writableArray[i], writableDestination, flags);
+                    writableDestination.write(",");
+                }
+            }
+            writableDestination.write(']');
+        } else {
+            /*
+             * TODO a potential feature for future release since POJOs are often
+             * represented as JsonObjects. It would be nice to have a flag that
+             * tries to reflectively figure out what a non-Jsonable POJO's
+             * fields are and use their names as keys and their respective
+             * values for the keys' values in the JsonObject? Naturally
+             * implementing Jsonable is safer and in many ways makes this
+             * feature a convenience for not needing to implement Jsonable for
+             * very simple POJOs. If it fails to produce a JsonObject to
+             * serialize it should defer to replacements if allowed. If
+             * replacement fails it should defer to invalids if allowed. This
+             * feature would require another serialize method exposed to allow
+             * this serialization. This feature (although perhaps useful on its
+             * own) would also include a method in the JsonObject where you pass
+             * it a class and it would do its best to instantiate a POJO of the
+             * class using the keys in the JsonObject.
+             */
+            /*
+             * It cannot by any measure be safely serialized according to
+             * specification.
+             */
+            if (flags.contains(SerializationOptions.ALLOW_INVALIDS)) {
+                /* Can be helpful for debugging how it isn't valid. */
+                writableDestination.write(jsonSerializable.toString());
+            } else {
+                /*
+                 * Notify the caller the cause of failure for the serialization.
+                 */
+                throw new IllegalArgumentException("Encountered a: " + jsonSerializable.getClass().getName() + " as: " + jsonSerializable
+                    .toString() + "  that isn't JSON serializable.\n  Try:\n    1) Implementing the Jsonable interface for the object to return valid JSON. If it already does it probably has a bug.\n    2) If you cannot edit the source of the object or couple it with this library consider wrapping it in a class that does implement the Jsonable interface.\n    3) Otherwise convert it to a boolean, null, number, JsonArray, JsonObject, or String value before serializing it.\n    4) If you f [...]
+            }
+        }
+        // System.out.println(writableDestination.toString());
+    }
 
-	/** Serializes like the first version of this library.
-	 * It has been adapted to use Jsonable for serializing custom objects, but otherwise works like the old JSON string
-	 * serializer. It
-	 * will allow non-JSON values in its output like the old one. It can be helpful for last resort log statements and
-	 * debugging errors in self generated JSON. Anything serialized using this method isn't guaranteed to be
-	 * deserializable.
-	 * @param jsonSerializable represents the object that should be serialized in JSON format.
-	 * @param writableDestination represents where the resulting JSON text is written to.
-	 * @throws IOException if the writableDestination encounters an I/O problem, like being closed while in use. */
-	public static void serializeCarelessly(final Object jsonSerializable, final Writer writableDestination) throws IOException{
-		Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.of(SerializationOptions.ALLOW_JSONABLES, SerializationOptions.ALLOW_INVALIDS));
-	}
+    /**
+     * Serializes like the first version of this library. It has been adapted to
+     * use Jsonable for serializing custom objects, but otherwise works like the
+     * old JSON string serializer. It will allow non-JSON values in its output
+     * like the old one. It can be helpful for last resort log statements and
+     * debugging errors in self generated JSON. Anything serialized using this
+     * method isn't guaranteed to be deserializable.
+     * 
+     * @param jsonSerializable represents the object that should be serialized
+     *            in JSON format.
+     * @param writableDestination represents where the resulting JSON text is
+     *            written to.
+     * @throws IOException if the writableDestination encounters an I/O problem,
+     *             like being closed while in use.
+     */
+    public static void serializeCarelessly(final Object jsonSerializable, final Writer writableDestination) throws IOException {
+        Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.of(SerializationOptions.ALLOW_JSONABLES, SerializationOptions.ALLOW_INVALIDS));
+    }
 
-	/** Serializes JSON values and only JSON values according to the RFC 4627 JSON specification.
-	 * @param jsonSerializable represents the object that should be serialized in JSON format.
-	 * @param writableDestination represents where the resulting JSON text is written to.
-	 * @throws IOException if the writableDestination encounters an I/O problem, like being closed while in use.
-	 * @throws IllegalArgumentException if the jsonSerializable isn't serializable in JSON. */
-	public static void serializeStrictly(final Object jsonSerializable, final Writer writableDestination) throws IOException{
-		Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.noneOf(SerializationOptions.class));
-	}
+    /**
+     * Serializes JSON values and only JSON values according to the RFC 4627
+     * JSON specification.
+     * 
+     * @param jsonSerializable represents the object that should be serialized
+     *            in JSON format.
+     * @param writableDestination represents where the resulting JSON text is
+     *            written to.
+     * @throws IOException if the writableDestination encounters an I/O problem,
+     *             like being closed while in use.
+     * @throws IllegalArgumentException if the jsonSerializable isn't
+     *             serializable in JSON.
+     */
+    public static void serializeStrictly(final Object jsonSerializable, final Writer writableDestination) throws IOException {
+        Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.noneOf(SerializationOptions.class));
+    }
 }
diff --git a/camel-util-json/src/main/java/org/apache/camel/util/json/Yylex.java b/camel-util-json/src/main/java/org/apache/camel/util/json/Yylex.java
index 1b48f15..5e36706 100644
--- a/camel-util-json/src/main/java/org/apache/camel/util/json/Yylex.java
+++ b/camel-util-json/src/main/java/org/apache/camel/util/json/Yylex.java
@@ -1,695 +1,646 @@
-/* The following code was generated by JFlex 1.4.3 on 8/30/16 5:50 PM */
+/**
+ * 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.camel.util.json;
 
-
 /**
- * This class is a scanner generated by 
- * <a href="http://www.jflex.de/">JFlex</a> 1.4.3
- * on 8/30/16 5:50 PM from the specification file
+ * This class is a scanner generated by <a href="http://www.jflex.de/">JFlex</a>
+ * 1.4.3 on 8/30/16 5:50 PM from the specification file
  * <tt>/home/davinloegering/cliftonlabs/workspace/json-simple/src/main/lex/jsonstrict.lex</tt>
  */
 class Yylex {
 
-  /** This character denotes the end of file */
-  public static final int YYEOF = -1;
-
-  /** initial size of the lookahead buffer */
-  private static final int ZZ_BUFFERSIZE = 16384;
-
-  /** lexical states */
-  public static final int YYINITIAL = 0;
-  public static final int STRING_BEGIN = 2;
-
-  /**
-   * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
-   * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
-   *                  at the beginning of a line
-   * l is of the form l = 2*k, k a non negative integer
-   */
-  private static final int ZZ_LEXSTATE[] = { 
-     0,  0,  1, 1
-  };
-
-  /** 
-   * Translates characters to character classes
-   */
-  private static final String ZZ_CMAP_PACKED = 
-    "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+
-    "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+
-    "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21"+
-    "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+
-    "\5\0\1\25\1\0\1\26\uff82\0";
-
-  /** 
-   * Translates characters to character classes
-   */
-  private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
-
-  /** 
-   * Translates DFA states to action switch labels.
-   */
-  private static final int [] ZZ_ACTION = zzUnpackAction();
-
-  private static final String ZZ_ACTION_PACKED_0 =
-    "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+
-    "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+
-    "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+
-    "\1\0\1\2\1\0\1\2\4\0\1\25\1\26\2\0"+
-    "\1\27";
-
-  private static int [] zzUnpackAction() {
-    int [] result = new int[45];
-    int offset = 0;
-    offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
-    return result;
-  }
-
-  private static int zzUnpackAction(String packed, int offset, int [] result) {
-    int i = 0;       /* index in packed string  */
-    int j = offset;  /* index in unpacked array */
-    int l = packed.length();
-    while (i < l) {
-      int count = packed.charAt(i++);
-      int value = packed.charAt(i++);
-      do result[j++] = value; while (--count > 0);
+    /** This character denotes the end of file */
+    public static final int YYEOF = -1;
+
+    /** initial size of the lookahead buffer */
+    private static final int ZZ_BUFFERSIZE = 16384;
+
+    /** lexical states */
+    public static final int YYINITIAL = 0;
+    public static final int STRING_BEGIN = 2;
+
+    /**
+     * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
+     * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l at the
+     * beginning of a line l is of the form l = 2*k, k a non negative integer
+     */
+    private static final int ZZ_LEXSTATE[] = {0, 0, 1, 1};
+
+    /**
+     * Translates characters to character classes
+     */
+    private static final String ZZ_CMAP_PACKED = "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0" + "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"
+                                                 + "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21" + "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"
+                                                 + "\5\0\1\25\1\0\1\26\uff82\0";
+
+    /**
+     * Translates characters to character classes
+     */
+    private static final char[] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+    /**
+     * Translates DFA states to action switch labels.
+     */
+    private static final int[] ZZ_ACTION = zzUnpackAction();
+
+    private static final String ZZ_ACTION_PACKED_0 = "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6" + "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0" + "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"
+                                                     + "\1\0\1\2\1\0\1\2\4\0\1\25\1\26\2\0" + "\1\27";
+
+    private static int[] zzUnpackAction() {
+        int[] result = new int[45];
+        int offset = 0;
+        offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+        return result;
     }
-    return j;
-  }
-
-
-  /** 
-   * Translates a state to a row index in the transition table
-   */
-  private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
-
-  private static final String ZZ_ROWMAP_PACKED_0 =
-    "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242"+
-    "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"+
-    "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+
-    "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"+
-    "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252"+
-    "\0\66\0\66\0\u026d\0\u0288\0\66";
-
-  private static int [] zzUnpackRowMap() {
-    int [] result = new int[45];
-    int offset = 0;
-    offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
-    return result;
-  }
-
-  private static int zzUnpackRowMap(String packed, int offset, int [] result) {
-    int i = 0;  /* index in packed string  */
-    int j = offset;  /* index in unpacked array */
-    int l = packed.length();
-    while (i < l) {
-      int high = packed.charAt(i++) << 16;
-      result[j++] = high | packed.charAt(i++);
+
+    private static int zzUnpackAction(String packed, int offset, int[] result) {
+        int i = 0; /* index in packed string */
+        int j = offset; /* index in unpacked array */
+        int l = packed.length();
+        while (i < l) {
+            int count = packed.charAt(i++);
+            int value = packed.charAt(i++);
+            do
+                result[j++] = value;
+            while (--count > 0);
+        }
+        return j;
     }
-    return j;
-  }
-
-  /** 
-   * The transition table of the DFA
-   */
-  private static final int ZZ_TRANS [] = {
-    2, 2, 3, 4, 2, 2, 2, 5, 2, 6, 
-    2, 2, 7, 8, 2, 9, 2, 2, 2, 2, 
-    2, 10, 11, 12, 13, 14, 15, 16, 16, 16, 
-    16, 16, 16, 16, 16, 17, 18, 16, 16, 16, 
-    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
-    16, 16, 16, 16, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, 4, 19, 20, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    21, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    23, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, 16, 16, 16, 16, 16, 16, 16, 
-    16, -1, -1, 16, 16, 16, 16, 16, 16, 16, 
-    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 
-    -1, -1, -1, -1, -1, -1, -1, -1, 24, 25, 
-    26, 27, 28, 29, 30, 31, 32, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    33, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, 34, 35, -1, -1, 
-    34, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    36, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, 39, -1, 39, -1, 39, -1, -1, 
-    -1, -1, -1, 39, 39, -1, -1, -1, -1, 39, 
-    39, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, 33, -1, 20, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, 
-    -1, -1, -1, -1, -1, 42, -1, 42, -1, 42, 
-    -1, -1, -1, -1, -1, 42, 42, -1, -1, -1, 
-    -1, 42, 42, -1, -1, -1, -1, -1, -1, -1, 
-    -1, -1, 43, -1, 43, -1, 43, -1, -1, -1, 
-    -1, -1, 43, 43, -1, -1, -1, -1, 43, 43, 
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, 
-    -1, 44, -1, 44, -1, -1, -1, -1, -1, 44, 
-    44, -1, -1, -1, -1, 44, 44, -1, -1, -1, 
-    -1, -1, -1, -1, -1, 
-  };
-
-  /* error codes */
-  private static final int ZZ_UNKNOWN_ERROR = 0;
-  private static final int ZZ_NO_MATCH = 1;
-  private static final int ZZ_PUSHBACK_2BIG = 2;
-
-  /* error messages for the codes above */
-  private static final String ZZ_ERROR_MSG[] = {
-    "Unkown internal scanner error",
-    "Error: could not match input",
-    "Error: pushback value was too large"
-  };
-
-  /**
-   * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
-   */
-  private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
-
-  private static final String ZZ_ATTRIBUTE_PACKED_0 =
-    "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11"+
-    "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11"+
-    "\2\0\1\11";
-
-  private static int [] zzUnpackAttribute() {
-    int [] result = new int[45];
-    int offset = 0;
-    offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
-    return result;
-  }
-
-  private static int zzUnpackAttribute(String packed, int offset, int [] result) {
-    int i = 0;       /* index in packed string  */
-    int j = offset;  /* index in unpacked array */
-    int l = packed.length();
-    while (i < l) {
-      int count = packed.charAt(i++);
-      int value = packed.charAt(i++);
-      do result[j++] = value; while (--count > 0);
+
+    /**
+     * Translates a state to a row index in the transition table
+     */
+    private static final int[] ZZ_ROWMAP = zzUnpackRowMap();
+
+    private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242" + "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"
+                                                     + "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195" + "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"
+                                                     + "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252" + "\0\66\0\66\0\u026d\0\u0288\0\66";
+
+    private static int[] zzUnpackRowMap() {
+        int[] result = new int[45];
+        int offset = 0;
+        offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+        return result;
     }
-    return j;
-  }
 
-  /** the input device */
-  private java.io.Reader zzReader;
+    private static int zzUnpackRowMap(String packed, int offset, int[] result) {
+        int i = 0; /* index in packed string */
+        int j = offset; /* index in unpacked array */
+        int l = packed.length();
+        while (i < l) {
+            int high = packed.charAt(i++) << 16;
+            result[j++] = high | packed.charAt(i++);
+        }
+        return j;
+    }
 
-  /** the current state of the DFA */
-  private int zzState;
+    /**
+     * The transition table of the DFA
+     */
+    private static final int ZZ_TRANS[] = {2, 2, 3, 4, 2, 2, 2, 5, 2, 6, 2, 2, 7, 8, 2, 9, 2, 2, 2, 2, 2, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 18, 16, 16,
+                                           16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, 4, 19, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           16, 16, 16, 16, 16, 16, 16, 16, -1, -1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, 35, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, 39, -1, 39, -1, -1, -1, -1, -1, 39, 39, -1, -1,
+                                           -1, -1, 39, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                                           -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, 42, -1, 42, -1, -1, -1, -1, -1, 42, 42, -1, -1, -1, -1, 42, 42, -1, -1, -1, -1,
+                                           -1, -1, -1, -1, -1, 43, -1, 43, -1, 43, -1, -1, -1, -1, -1, 43, 43, -1, -1, -1, -1, 43, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1,
+                                           44, -1, 44, -1, -1, -1, -1, -1, 44, 44, -1, -1, -1, -1, 44, 44, -1, -1, -1, -1, -1, -1, -1, -1,};
+
+    /* error codes */
+    private static final int ZZ_UNKNOWN_ERROR = 0;
+    private static final int ZZ_NO_MATCH = 1;
+    private static final int ZZ_PUSHBACK_2BIG = 2;
+
+    /* error messages for the codes above */
+    private static final String ZZ_ERROR_MSG[] = {"Unkown internal scanner error", "Error: could not match input", "Error: pushback value was too large"};
+
+    /**
+     * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+     */
+    private static final int[] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+    private static final String ZZ_ATTRIBUTE_PACKED_0 = "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11" + "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11" + "\2\0\1\11";
+
+    private static int[] zzUnpackAttribute() {
+        int[] result = new int[45];
+        int offset = 0;
+        offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+        return result;
+    }
 
-  /** the current lexical state */
-  private int zzLexicalState = YYINITIAL;
+    private static int zzUnpackAttribute(String packed, int offset, int[] result) {
+        int i = 0; /* index in packed string */
+        int j = offset; /* index in unpacked array */
+        int l = packed.length();
+        while (i < l) {
+            int count = packed.charAt(i++);
+            int value = packed.charAt(i++);
+            do
+                result[j++] = value;
+            while (--count > 0);
+        }
+        return j;
+    }
 
-  /** this buffer contains the current text to be matched and is
-      the source of the yytext() string */
-  private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+    /** the input device */
+    private java.io.Reader zzReader;
 
-  /** the textposition at the last accepting state */
-  private int zzMarkedPos;
+    /** the current state of the DFA */
+    private int zzState;
 
-  /** the current text position in the buffer */
-  private int zzCurrentPos;
+    /** the current lexical state */
+    private int zzLexicalState = YYINITIAL;
 
-  /** startRead marks the beginning of the yytext() string in the buffer */
-  private int zzStartRead;
+    /**
+     * this buffer contains the current text to be matched and is the source of
+     * the yytext() string
+     */
+    private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
 
-  /** endRead marks the last character in the buffer, that has been read
-      from input */
-  private int zzEndRead;
+    /** the textposition at the last accepting state */
+    private int zzMarkedPos;
 
-  /** number of newlines encountered up to the start of the matched text */
-  private int yyline;
+    /** the current text position in the buffer */
+    private int zzCurrentPos;
 
-  /** the number of characters up to the start of the matched text */
-  private int yychar;
+    /** startRead marks the beginning of the yytext() string in the buffer */
+    private int zzStartRead;
 
-  /**
-   * the number of characters from the last newline up to the start of the 
-   * matched text
-   */
-  private int yycolumn;
+    /**
+     * endRead marks the last character in the buffer, that has been read from
+     * input
+     */
+    private int zzEndRead;
 
-  /** 
-   * zzAtBOL == true <=> the scanner is currently at the beginning of a line
-   */
-  private boolean zzAtBOL = true;
+    /** number of newlines encountered up to the start of the matched text */
+    private int yyline;
 
-  /** zzAtEOF == true <=> the scanner is at the EOF */
-  private boolean zzAtEOF;
+    /** the number of characters up to the start of the matched text */
+    private int yychar;
 
-  /** denotes if the user-EOF-code has already been executed */
-  private boolean zzEOFDone;
+    /**
+     * the number of characters from the last newline up to the start of the
+     * matched text
+     */
+    private int yycolumn;
 
-  /* user code: */
-private StringBuilder sb=new StringBuilder();
+    /**
+     * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+     */
+    private boolean zzAtBOL = true;
 
-int getPosition(){
-	return yychar;
-}
+    /** zzAtEOF == true <=> the scanner is at the EOF */
+    private boolean zzAtEOF;
 
+    /** denotes if the user-EOF-code has already been executed */
+    private boolean zzEOFDone;
 
+    /* user code: */
+    private StringBuilder sb = new StringBuilder();
 
-  /**
-   * Creates a new scanner
-   * There is also a java.io.InputStream version of this constructor.
-   *
-   * @param   in  the java.io.Reader to read input from.
-   */
-  Yylex(java.io.Reader in) {
-    this.zzReader = in;
-  }
-
-  /**
-   * Creates a new scanner.
-   * There is also java.io.Reader version of this constructor.
-   *
-   * @param   in  the java.io.Inputstream to read input from.
-   */
-  Yylex(java.io.InputStream in) {
-    this(new java.io.InputStreamReader(in));
-  }
-
-  /** 
-   * Unpacks the compressed character translation table.
-   *
-   * @param packed   the packed character translation table
-   * @return         the unpacked character translation table
-   */
-  private static char [] zzUnpackCMap(String packed) {
-    char [] map = new char[0x10000];
-    int i = 0;  /* index in packed string  */
-    int j = 0;  /* index in unpacked array */
-    while (i < 90) {
-      int  count = packed.charAt(i++);
-      char value = packed.charAt(i++);
-      do map[j++] = value; while (--count > 0);
-    }
-    return map;
-  }
-
-
-  /**
-   * Refills the input buffer.
-   *
-   * @return      <code>false</code>, iff there was new input.
-   * 
-   * @exception   java.io.IOException  if any I/O-Error occurs
-   */
-  private boolean zzRefill() throws java.io.IOException {
-
-    /* first: make room (if you can) */
-    if (zzStartRead > 0) {
-      System.arraycopy(zzBuffer, zzStartRead,
-                       zzBuffer, 0,
-                       zzEndRead-zzStartRead);
-
-      /* translate stored positions */
-      zzEndRead-= zzStartRead;
-      zzCurrentPos-= zzStartRead;
-      zzMarkedPos-= zzStartRead;
-      zzStartRead = 0;
+    int getPosition() {
+        return yychar;
     }
 
-    /* is the buffer big enough? */
-    if (zzCurrentPos >= zzBuffer.length) {
-      /* if not: blow it up */
-      char newBuffer[] = new char[zzCurrentPos*2];
-      System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
-      zzBuffer = newBuffer;
+    /**
+     * Creates a new scanner There is also a java.io.InputStream version of this
+     * constructor.
+     *
+     * @param in the java.io.Reader to read input from.
+     */
+    Yylex(java.io.Reader in) {
+        this.zzReader = in;
     }
 
-    /* finally: fill the buffer with new input */
-    int numRead = zzReader.read(zzBuffer, zzEndRead,
-                                            zzBuffer.length-zzEndRead);
+    /**
+     * Creates a new scanner. There is also java.io.Reader version of this
+     * constructor.
+     *
+     * @param in the java.io.Inputstream to read input from.
+     */
+    Yylex(java.io.InputStream in) {
+        this(new java.io.InputStreamReader(in));
+    }
 
-    if (numRead > 0) {
-      zzEndRead+= numRead;
-      return false;
+    /**
+     * Unpacks the compressed character translation table.
+     *
+     * @param packed the packed character translation table
+     * @return the unpacked character translation table
+     */
+    private static char[] zzUnpackCMap(String packed) {
+        char[] map = new char[0x10000];
+        int i = 0; /* index in packed string */
+        int j = 0; /* index in unpacked array */
+        while (i < 90) {
+            int count = packed.charAt(i++);
+            char value = packed.charAt(i++);
+            do
+                map[j++] = value;
+            while (--count > 0);
+        }
+        return map;
     }
-    // unlikely but not impossible: read 0 characters, but not at end of stream    
-    if (numRead == 0) {
-      int c = zzReader.read();
-      if (c == -1) {
+
+    /**
+     * Refills the input buffer.
+     *
+     * @return <code>false</code>, iff there was new input.
+     * @exception java.io.IOException if any I/O-Error occurs
+     */
+    private boolean zzRefill() throws java.io.IOException {
+
+        /* first: make room (if you can) */
+        if (zzStartRead > 0) {
+            System.arraycopy(zzBuffer, zzStartRead, zzBuffer, 0, zzEndRead - zzStartRead);
+
+            /* translate stored positions */
+            zzEndRead -= zzStartRead;
+            zzCurrentPos -= zzStartRead;
+            zzMarkedPos -= zzStartRead;
+            zzStartRead = 0;
+        }
+
+        /* is the buffer big enough? */
+        if (zzCurrentPos >= zzBuffer.length) {
+            /* if not: blow it up */
+            char newBuffer[] = new char[zzCurrentPos * 2];
+            System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+            zzBuffer = newBuffer;
+        }
+
+        /* finally: fill the buffer with new input */
+        int numRead = zzReader.read(zzBuffer, zzEndRead, zzBuffer.length - zzEndRead);
+
+        if (numRead > 0) {
+            zzEndRead += numRead;
+            return false;
+        }
+        // unlikely but not impossible: read 0 characters, but not at end of
+        // stream
+        if (numRead == 0) {
+            int c = zzReader.read();
+            if (c == -1) {
+                return true;
+            } else {
+                zzBuffer[zzEndRead++] = (char)c;
+                return false;
+            }
+        }
+
+        // numRead < 0
         return true;
-      } else {
-        zzBuffer[zzEndRead++] = (char) c;
-        return false;
-      }     
     }
 
-	// numRead < 0
-    return true;
-  }
-
-    
-  /**
-   * Closes the input stream.
-   */
-  public final void yyclose() throws java.io.IOException {
-    zzAtEOF = true;            /* indicate end of file */
-    zzEndRead = zzStartRead;  /* invalidate buffer    */
-
-    if (zzReader != null)
-      zzReader.close();
-  }
-
-
-  /**
-   * Resets the scanner to read from a new input stream.
-   * Does not close the old reader.
-   *
-   * All internal variables are reset, the old input stream 
-   * <b>cannot</b> be reused (internal buffer is discarded and lost).
-   * Lexical state is set to <tt>ZZ_INITIAL</tt>.
-   *
-   * @param reader   the new input stream 
-   */
-  public final void yyreset(java.io.Reader reader) {
-    zzReader = reader;
-    zzAtBOL  = true;
-    zzAtEOF  = false;
-    zzEOFDone = false;
-    zzEndRead = zzStartRead = 0;
-    zzCurrentPos = zzMarkedPos = 0;
-    yyline = yychar = yycolumn = 0;
-    zzLexicalState = YYINITIAL;
-  }
-
-
-  /**
-   * Returns the current lexical state.
-   */
-  public final int yystate() {
-    return zzLexicalState;
-  }
-
-
-  /**
-   * Enters a new lexical state
-   *
-   * @param newState the new lexical state
-   */
-  public final void yybegin(int newState) {
-    zzLexicalState = newState;
-  }
-
-
-  /**
-   * Returns the text matched by the current regular expression.
-   */
-  public final String yytext() {
-    return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
-  }
-
-
-  /**
-   * Returns the character at position <tt>pos</tt> from the 
-   * matched text. 
-   * 
-   * It is equivalent to yytext().charAt(pos), but faster
-   *
-   * @param pos the position of the character to fetch. 
-   *            A value from 0 to yylength()-1.
-   *
-   * @return the character at position pos
-   */
-  public final char yycharat(int pos) {
-    return zzBuffer[zzStartRead+pos];
-  }
-
-
-  /**
-   * Returns the length of the matched text region.
-   */
-  public final int yylength() {
-    return zzMarkedPos-zzStartRead;
-  }
-
-
-  /**
-   * Reports an error that occured while scanning.
-   *
-   * In a wellformed scanner (no or only correct usage of 
-   * yypushback(int) and a match-all fallback rule) this method 
-   * will only be called with things that "Can't Possibly Happen".
-   * If this method is called, something is seriously wrong
-   * (e.g. a JFlex bug producing a faulty scanner etc.).
-   *
-   * Usual syntax/scanner level error handling should be done
-   * in error fallback rules.
-   *
-   * @param   errorCode  the code of the errormessage to display
-   */
-  private void zzScanError(int errorCode) {
-    String message;
-    try {
-      message = ZZ_ERROR_MSG[errorCode];
-    }
-    catch (ArrayIndexOutOfBoundsException e) {
-      message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
-    }
+    /**
+     * Closes the input stream.
+     */
+    public final void yyclose() throws java.io.IOException {
+        zzAtEOF = true; /* indicate end of file */
+        zzEndRead = zzStartRead; /* invalidate buffer */
 
-    throw new Error(message);
-  } 
+        if (zzReader != null)
+            zzReader.close();
+    }
 
+    /**
+     * Resets the scanner to read from a new input stream. Does not close the
+     * old reader. All internal variables are reset, the old input stream
+     * <b>cannot</b> be reused (internal buffer is discarded and lost). Lexical
+     * state is set to <tt>ZZ_INITIAL</tt>.
+     *
+     * @param reader the new input stream
+     */
+    public final void yyreset(java.io.Reader reader) {
+        zzReader = reader;
+        zzAtBOL = true;
+        zzAtEOF = false;
+        zzEOFDone = false;
+        zzEndRead = zzStartRead = 0;
+        zzCurrentPos = zzMarkedPos = 0;
+        yyline = yychar = yycolumn = 0;
+        zzLexicalState = YYINITIAL;
+    }
 
-  /**
-   * Pushes the specified amount of characters back into the input stream.
-   *
-   * They will be read again by then next call of the scanning method
-   *
-   * @param number  the number of characters to be read again.
-   *                This number must not be greater than yylength()!
-   */
-  public void yypushback(int number)  {
-    if ( number > yylength() )
-      zzScanError(ZZ_PUSHBACK_2BIG);
+    /**
+     * Returns the current lexical state.
+     */
+    public final int yystate() {
+        return zzLexicalState;
+    }
 
-    zzMarkedPos -= number;
-  }
+    /**
+     * Enters a new lexical state
+     *
+     * @param newState the new lexical state
+     */
+    public final void yybegin(int newState) {
+        zzLexicalState = newState;
+    }
 
+    /**
+     * Returns the text matched by the current regular expression.
+     */
+    public final String yytext() {
+        return new String(zzBuffer, zzStartRead, zzMarkedPos - zzStartRead);
+    }
 
-  /**
-   * Resumes scanning until the next regular expression is matched,
-   * the end of input is encountered or an I/O-Error occurs.
-   *
-   * @return      the next token
-   * @exception   java.io.IOException  if any I/O-Error occurs
-   */
-  public Yytoken yylex() throws java.io.IOException, DeserializationException {
-    int zzInput;
-    int zzAction;
+    /**
+     * Returns the character at position <tt>pos</tt> from the matched text. It
+     * is equivalent to yytext().charAt(pos), but faster
+     *
+     * @param pos the position of the character to fetch. A value from 0 to
+     *            yylength()-1.
+     * @return the character at position pos
+     */
+    public final char yycharat(int pos) {
+        return zzBuffer[zzStartRead + pos];
+    }
 
-    // cached fields:
-    int zzCurrentPosL;
-    int zzMarkedPosL;
-    int zzEndReadL = zzEndRead;
-    char [] zzBufferL = zzBuffer;
-    char [] zzCMapL = ZZ_CMAP;
+    /**
+     * Returns the length of the matched text region.
+     */
+    public final int yylength() {
+        return zzMarkedPos - zzStartRead;
+    }
 
-    int [] zzTransL = ZZ_TRANS;
-    int [] zzRowMapL = ZZ_ROWMAP;
-    int [] zzAttrL = ZZ_ATTRIBUTE;
+    /**
+     * Reports an error that occured while scanning. In a wellformed scanner (no
+     * or only correct usage of yypushback(int) and a match-all fallback rule)
+     * this method will only be called with things that "Can't Possibly Happen".
+     * If this method is called, something is seriously wrong (e.g. a JFlex bug
+     * producing a faulty scanner etc.). Usual syntax/scanner level error
+     * handling should be done in error fallback rules.
+     *
+     * @param errorCode the code of the errormessage to display
+     */
+    private void zzScanError(int errorCode) {
+        String message;
+        try {
+            message = ZZ_ERROR_MSG[errorCode];
+        } catch (ArrayIndexOutOfBoundsException e) {
+            message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+        }
 
-    while (true) {
-      zzMarkedPosL = zzMarkedPos;
+        throw new Error(message);
+    }
 
-      yychar+= zzMarkedPosL-zzStartRead;
+    /**
+     * Pushes the specified amount of characters back into the input stream.
+     * They will be read again by then next call of the scanning method
+     *
+     * @param number the number of characters to be read again. This number must
+     *            not be greater than yylength()!
+     */
+    public void yypushback(int number) {
+        if (number > yylength())
+            zzScanError(ZZ_PUSHBACK_2BIG);
+
+        zzMarkedPos -= number;
+    }
 
-      zzAction = -1;
+    /**
+     * Resumes scanning until the next regular expression is matched, the end of
+     * input is encountered or an I/O-Error occurs.
+     *
+     * @return the next token
+     * @exception java.io.IOException if any I/O-Error occurs
+     */
+    public Yytoken yylex() throws java.io.IOException, DeserializationException {
+        int zzInput;
+        int zzAction;
+
+        // cached fields:
+        int zzCurrentPosL;
+        int zzMarkedPosL;
+        int zzEndReadL = zzEndRead;
+        char[] zzBufferL = zzBuffer;
+        char[] zzCMapL = ZZ_CMAP;
+
+        int[] zzTransL = ZZ_TRANS;
+        int[] zzRowMapL = ZZ_ROWMAP;
+        int[] zzAttrL = ZZ_ATTRIBUTE;
 
-      zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
-  
-      zzState = ZZ_LEXSTATE[zzLexicalState];
+        while (true) {
+            zzMarkedPosL = zzMarkedPos;
+
+            yychar += zzMarkedPosL - zzStartRead;
+
+            zzAction = -1;
+
+            zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+            zzState = ZZ_LEXSTATE[zzLexicalState];
+
+            zzForAction: {
+                while (true) {
+
+                    if (zzCurrentPosL < zzEndReadL)
+                        zzInput = zzBufferL[zzCurrentPosL++];
+                    else if (zzAtEOF) {
+                        zzInput = YYEOF;
+                        break zzForAction;
+                    } else {
+                        // store back cached positions
+                        zzCurrentPos = zzCurrentPosL;
+                        zzMarkedPos = zzMarkedPosL;
+                        boolean eof = zzRefill();
+                        // get translated positions and possibly new buffer
+                        zzCurrentPosL = zzCurrentPos;
+                        zzMarkedPosL = zzMarkedPos;
+                        zzBufferL = zzBuffer;
+                        zzEndReadL = zzEndRead;
+                        if (eof) {
+                            zzInput = YYEOF;
+                            break zzForAction;
+                        } else {
+                            zzInput = zzBufferL[zzCurrentPosL++];
+                        }
+                    }
+                    int zzNext = zzTransL[zzRowMapL[zzState] + zzCMapL[zzInput]];
+                    if (zzNext == -1)
+                        break zzForAction;
+                    zzState = zzNext;
+
+                    int zzAttributes = zzAttrL[zzState];
+                    if ((zzAttributes & 1) == 1) {
+                        zzAction = zzState;
+                        zzMarkedPosL = zzCurrentPosL;
+                        if ((zzAttributes & 8) == 8)
+                            break zzForAction;
+                    }
+
+                }
+            }
 
+            // store back cached position
+            zzMarkedPos = zzMarkedPosL;
 
-      zzForAction: {
-        while (true) {
-    
-          if (zzCurrentPosL < zzEndReadL)
-            zzInput = zzBufferL[zzCurrentPosL++];
-          else if (zzAtEOF) {
-            zzInput = YYEOF;
-            break zzForAction;
-          }
-          else {
-            // store back cached positions
-            zzCurrentPos  = zzCurrentPosL;
-            zzMarkedPos   = zzMarkedPosL;
-            boolean eof = zzRefill();
-            // get translated positions and possibly new buffer
-            zzCurrentPosL  = zzCurrentPos;
-            zzMarkedPosL   = zzMarkedPos;
-            zzBufferL      = zzBuffer;
-            zzEndReadL     = zzEndRead;
-            if (eof) {
-              zzInput = YYEOF;
-              break zzForAction;
+            switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+            case 4: {
+                sb = null;
+                sb = new StringBuilder();
+                yybegin(STRING_BEGIN);
             }
-            else {
-              zzInput = zzBufferL[zzCurrentPosL++];
+            case 24:
+                break;
+            case 11: {
+                sb.append(yytext());
+            }
+            case 25:
+                break;
+            case 5: {
+                return new Yytoken(Yytoken.Types.LEFT_BRACE, null);
+            }
+            case 26:
+                break;
+            case 16: {
+                sb.append('\b');
+            }
+            case 27:
+                break;
+            case 23: {
+                try {
+                    int ch = Integer.parseInt(yytext().substring(2), 16);
+                    sb.append((char)ch);
+                } catch (Exception e) {
+                    /*
+                     * The lexer is broken if it can build a 4 byte character
+                     * code and fail to append the character.
+                     */
+                    throw new DeserializationException(yychar, DeserializationException.Problems.UNEXPECTED_EXCEPTION, e);
+                }
+            }
+            case 28:
+                break;
+            case 22: {
+                Boolean val = Boolean.valueOf(yytext());
+                return new Yytoken(Yytoken.Types.DATUM, val);
+            }
+            case 29:
+                break;
+            case 12: {
+                sb.append('\\');
+            }
+            case 30:
+                break;
+            case 10: {
+                return new Yytoken(Yytoken.Types.COLON, null);
+            }
+            case 31:
+                break;
+            case 9: {
+                return new Yytoken(Yytoken.Types.COMMA, null);
+            }
+            case 32:
+                break;
+            case 21: {
+                return new Yytoken(Yytoken.Types.DATUM, null);
+            }
+            case 33:
+                break;
+            case 19: {
+                sb.append('\r');
+            }
+            case 34:
+                break;
+            case 15: {
+                sb.append('/');
+            }
+            case 35:
+                break;
+            case 2: {
+                java.math.BigDecimal val = new java.math.BigDecimal(yytext());
+                return new Yytoken(Yytoken.Types.DATUM, val);
+            }
+            case 36:
+                break;
+            case 14: {
+                sb.append('"');
+            }
+            case 37:
+                break;
+            case 8: {
+                return new Yytoken(Yytoken.Types.RIGHT_SQUARE, null);
+            }
+            case 38:
+                break;
+            case 17: {
+                sb.append('\f');
+            }
+            case 39:
+                break;
+            case 1: {
+                throw new DeserializationException(yychar, DeserializationException.Problems.UNEXPECTED_CHARACTER, new Character(yycharat(0)));
+            }
+            case 40:
+                break;
+            case 6: {
+                return new Yytoken(Yytoken.Types.RIGHT_BRACE, null);
+            }
+            case 41:
+                break;
+            case 20: {
+                sb.append('\t');
+            }
+            case 42:
+                break;
+            case 7: {
+                return new Yytoken(Yytoken.Types.LEFT_SQUARE, null);
+            }
+            case 43:
+                break;
+            case 18: {
+                sb.append('\n');
+            }
+            case 44:
+                break;
+            case 13: {
+                yybegin(YYINITIAL);
+                return new Yytoken(Yytoken.Types.DATUM, sb.toString());
+            }
+            case 45:
+                break;
+            case 3: {
+            }
+            case 46:
+                break;
+            default:
+                if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+                    zzAtEOF = true;
+                    return null;
+                } else {
+                    zzScanError(ZZ_NO_MATCH);
+                }
             }
-          }
-          int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
-          if (zzNext == -1) break zzForAction;
-          zzState = zzNext;
-
-          int zzAttributes = zzAttrL[zzState];
-          if ( (zzAttributes & 1) == 1 ) {
-            zzAction = zzState;
-            zzMarkedPosL = zzCurrentPosL;
-            if ( (zzAttributes & 8) == 8 ) break zzForAction;
-          }
-
         }
-      }
-
-      // store back cached position
-      zzMarkedPos = zzMarkedPosL;
-
-      switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
-        case 4: 
-          { sb = null; sb = new StringBuilder(); yybegin(STRING_BEGIN);
-          }
-        case 24: break;
-        case 11: 
-          { sb.append(yytext());
-          }
-        case 25: break;
-        case 5: 
-          { return new Yytoken(Yytoken.Types.LEFT_BRACE, null);
-          }
-        case 26: break;
-        case 16: 
-          { sb.append('\b');
-          }
-        case 27: break;
-        case 23: 
-          { try{
-			int ch=Integer.parseInt(yytext().substring(2),16);
-			sb.append((char)ch);
-		}catch(Exception e){
-			/* The lexer is broken if it can build a 4 byte character code and fail to append the character. */
-			throw new DeserializationException(yychar, DeserializationException.Problems.UNEXPECTED_EXCEPTION, e);
-		}
-          }
-        case 28: break;
-        case 22: 
-          { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.Types.DATUM, val);
-          }
-        case 29: break;
-        case 12: 
-          { sb.append('\\');
-          }
-        case 30: break;
-        case 10: 
-          { return new Yytoken(Yytoken.Types.COLON, null);
-          }
-        case 31: break;
-        case 9: 
-          { return new Yytoken(Yytoken.Types.COMMA, null);
-          }
-        case 32: break;
-        case 21: 
-          { return new Yytoken(Yytoken.Types.DATUM, null);
-          }
-        case 33: break;
-        case 19: 
-          { sb.append('\r');
-          }
-        case 34: break;
-        case 15: 
-          { sb.append('/');
-          }
-        case 35: break;
-        case 2: 
-          { java.math.BigDecimal val= new java.math.BigDecimal(yytext()); return new Yytoken(Yytoken.Types.DATUM, val);
-          }
-        case 36: break;
-        case 14: 
-          { sb.append('"');
-          }
-        case 37: break;
-        case 8: 
-          { return new Yytoken(Yytoken.Types.RIGHT_SQUARE, null);
-          }
-        case 38: break;
-        case 17: 
-          { sb.append('\f');
-          }
-        case 39: break;
-        case 1: 
-          { throw new DeserializationException(yychar, DeserializationException.Problems.UNEXPECTED_CHARACTER, new Character(yycharat(0)));
-          }
-        case 40: break;
-        case 6: 
-          { return new Yytoken(Yytoken.Types.RIGHT_BRACE, null);
-          }
-        case 41: break;
-        case 20: 
-          { sb.append('\t');
-          }
-        case 42: break;
-        case 7: 
-          { return new Yytoken(Yytoken.Types.LEFT_SQUARE, null);
-          }
-        case 43: break;
-        case 18: 
-          { sb.append('\n');
-          }
-        case 44: break;
-        case 13: 
-          { yybegin(YYINITIAL);return new Yytoken(Yytoken.Types.DATUM, sb.toString());
-          }
-        case 45: break;
-        case 3: 
-          { 
-          }
-        case 46: break;
-        default: 
-          if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
-            zzAtEOF = true;
-            return null;
-          } 
-          else {
-            zzScanError(ZZ_NO_MATCH);
-          }
-      }
     }
-  }
-
 
 }
diff --git a/camel-util-json/src/main/java/org/apache/camel/util/json/Yytoken.java b/camel-util-json/src/main/java/org/apache/camel/util/json/Yytoken.java
index bed0759..35e443e 100644
--- a/camel-util-json/src/main/java/org/apache/camel/util/json/Yytoken.java
+++ b/camel-util-json/src/main/java/org/apache/camel/util/json/Yytoken.java
@@ -1,25 +1,37 @@
-/* Copyright 2016 Clifton Labs
- * Licensed 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
+/**
+ * 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. */
+ * limitations under the License.
+ */
 package org.apache.camel.util.json;
 
-/** Represents structural entities in JSON.
- * @since 2.0.0 */
-class Yytoken{
+/**
+ * Represents structural entities in JSON.
+ * 
+ * @since 2.0.0
+ */
+class Yytoken {
     /** Represents the different kinds of tokens. */
-    enum Types{
+    enum Types {
         /** Tokens of this type will always have a value of ":" */
         COLON,
         /** Tokens of this type will always have a value of "," */
         COMMA,
-        /** Tokens of this type will always have a value that is a boolean, null, number, or string. */
+        /**
+         * Tokens of this type will always have a value that is a boolean, null,
+         * number, or string.
+         */
         DATUM,
         /** Tokens of this type will always have a value of "" */
         END,
@@ -33,58 +45,67 @@ class Yytoken{
         RIGHT_SQUARE;
     }
 
-    private final Types  type;
+    private final Types type;
     private final Object value;
 
-    /** @param type represents the kind of token the instantiated token will be.
-     * @param value represents the value the token is associated with, will be ignored unless type is equal to
-     *        Types.DATUM.
-     * @see Types */
-    Yytoken(final Types type, final Object value){
-        /* Sanity check. Make sure the value is ignored for the proper value unless it is a datum token. */
-        switch(type){
-            case COLON:
-                this.value = ":";
-                break;
-            case COMMA:
-                this.value = ",";
-                break;
-            case END:
-                this.value = "";
-                break;
-            case LEFT_BRACE:
-                this.value = "{";
-                break;
-            case LEFT_SQUARE:
-                this.value = "[";
-                break;
-            case RIGHT_BRACE:
-                this.value = "}";
-                break;
-            case RIGHT_SQUARE:
-                this.value = "]";
-                break;
-            default:
-                this.value = value;
-                break;
+    /**
+     * @param type represents the kind of token the instantiated token will be.
+     * @param value represents the value the token is associated with, will be
+     *            ignored unless type is equal to Types.DATUM.
+     * @see Types
+     */
+    Yytoken(final Types type, final Object value) {
+        /*
+         * Sanity check. Make sure the value is ignored for the proper value
+         * unless it is a datum token.
+         */
+        switch (type) {
+        case COLON:
+            this.value = ":";
+            break;
+        case COMMA:
+            this.value = ",";
+            break;
+        case END:
+            this.value = "";
+            break;
+        case LEFT_BRACE:
+            this.value = "{";
+            break;
+        case LEFT_SQUARE:
+            this.value = "[";
+            break;
+        case RIGHT_BRACE:
+            this.value = "}";
+            break;
+        case RIGHT_SQUARE:
+            this.value = "]";
+            break;
+        default:
+            this.value = value;
+            break;
         }
         this.type = type;
     }
 
-    /** @return which of the Types the token is.
-     * @see Types */
-    Types getType(){
+    /**
+     * @return which of the Types the token is.
+     * @see Types
+     */
+    Types getType() {
         return this.type;
     }
 
-    /** @return what the token is.
-     * @see Types */
-    Object getValue(){
+    /**
+     * @return what the token is.
+     * @see Types
+     */
+    Object getValue() {
         return this.value;
     }
 
     @Override
-    public String toString(){
+    public String toString() {
         final StringBuffer sb = new StringBuffer();
         sb.append(this.type.toString()).append("(").append(this.value).append(")");
         return sb.toString();