src/main/java/com/cedarsoftware/util/io/Resolver.java
protected Object createJavaObjectInstance(Class clazz, JsonObject jsonObj)
    {
        final boolean useMapsLocal = useMaps;
        String type = jsonObj.type;

        // We can't set values to an Object, so well try to use the contained type instead
		if ("java.lang.Object".equals(type))
        {
			Object value = jsonObj.get("value");
        	if (jsonObj.keySet().size() == 1 && value != null)
            {
        		type = value.getClass().getName();
        	}
        }

        Object mate;

        // @type always takes precedence over inferred Java (clazz) type.
        if (type != null)
        {    // @type is explicitly set, use that as it always takes precedence
            Class c;
            try
            {
                c = MetaUtils.classForName(type, reader.getClassLoader(), failOnUnknownType);
            }
            catch (Exception e)
            {
                if (useMapsLocal)
                {
                    jsonObj.type = null;
                    jsonObj.target = null;
                    return jsonObj;
                }
                else
                {
                    String name = clazz == null ? "null" : clazz.getName();
                    throw new JsonIoException("Unable to create class: " + name, e);
                }
            }
            if (c.isArray())
            {    // Handle []
                Object[] items = jsonObj.getArray();
                int size = (items == null) ? 0 : items.length;
                if (c == char[].class)
                {
                    jsonObj.moveCharsToMate();
                    mate = jsonObj.target;
                }
                else
                {
                    mate = Array.newInstance(c.getComponentType(), size);
                }
            }
            else
            {    // Handle regular field.object reference
                if (MetaUtils.isPrimitive(c))
                {
                    mate = MetaUtils.convert(c, jsonObj.get("value"));
                }
                else if (c == Class.class)
                {
                    mate = MetaUtils.classForName((String) jsonObj.get("value"), reader.getClassLoader());
                }
                else if (c.isEnum())
                {
                    mate = getEnum(c, jsonObj);
                }
                else if (Enum.class.isAssignableFrom(c)) // anonymous subclass of an enum
                {
                    mate = getEnum(c.getSuperclass(), jsonObj);
                }
                else if (EnumSet.class.isAssignableFrom(c))
                {
                    mate = getEnumSet(c, jsonObj);
                }
                else if ((mate = coerceCertainTypes(c.getName())) != null)
                {   // if coerceCertainTypes() returns non-null, it did the work
                }
                else
                {
                    mate = newInstance(c, jsonObj);
                }
            }
        }
        else
        {    // @type, not specified, figure out appropriate type
            Object[] items = jsonObj.getArray();

            // if @items is specified, it must be an [] type.
            // if clazz.isArray(), then it must be an [] type.
            if (clazz.isArray() || (items != null && clazz == Object.class && !jsonObj.containsKey("@keys")))
            {
                int size = (items == null) ? 0 : items.length;
                mate = Array.newInstance(clazz.isArray() ? clazz.getComponentType() : Object.class, size);
            }
            else if (clazz.isEnum())
            {
                mate = getEnum(clazz, jsonObj);
            }
            else if (Enum.class.isAssignableFrom(clazz)) // anonymous subclass of an enum
            {
                mate = getEnum(clazz.getSuperclass(), jsonObj);
            }
            else if (EnumSet.class.isAssignableFrom(clazz)) // anonymous subclass of an enum
            {
                mate = getEnumSet(clazz, jsonObj);
            }
            else if ((mate = coerceCertainTypes(clazz.getName())) != null)
            {   // if coerceCertainTypes() returns non-null, it did the work
            }
            else if (clazz == Object.class && !useMapsLocal)
            {
                if (unknownClass == null)
                {
                    mate = new JsonObject();
                    ((JsonObject)mate).type = Map.class.getName();
                }
                else if (unknownClass instanceof String)
                {
                    mate = newInstance(MetaUtils.classForName(((String)unknownClass).trim(), reader.getClassLoader()), jsonObj);
                }
                else
                {
                    throw new JsonIoException("Unable to determine object type at column: " + jsonObj.col + ", line: " + jsonObj.line + ", content: " + jsonObj);
                }
            }
            else
            {
                mate = newInstance(clazz, jsonObj);
            }
        }
        jsonObj.target = mate;
        return jsonObj.target;
    }
protected Object createJavaObjectInstance(Class clazz, JsonObject jsonObj)
    {
        final boolean useMapsLocal = useMaps;
        String type = jsonObj.type;

        // We can't set values to an Object, so well try to use the contained type instead
		if ("java.lang.Object".equals(type))
        {
			Object value = jsonObj.get("value");
        	if (jsonObj.keySet().size() == 1 && value != null)
            {
        		type = value.getClass().getName();
        	}
        }

        Object mate;

        // @type always takes precedence over inferred Java (clazz) type.
        if (type != null)
        {    // @type is explicitly set, use that as it always takes precedence
            Class c;
            try
            {
                c = MetaUtils.classForName(type, reader.getClassLoader(), failOnUnknownType);
            }
            catch (Exception e)
            {
                if (useMapsLocal)
                {
                    jsonObj.type = null;
                    jsonObj.target = null;
                    return jsonObj;
                }
                else
                {
                    String name = clazz == null ? "null" : clazz.getName();
                    throw new JsonIoException("Unable to create class: " + name, e);
                }
            }
            if (c.isArray())
            {    // Handle []
                Object[] items = jsonObj.getArray();
                int size = (items == null) ? 0 : items.length;
                if (c == char[].class)
                {
                    jsonObj.moveCharsToMate();
                    mate = jsonObj.target;
                }
                else
                {
                    mate = Array.newInstance(c.getComponentType(), size);
                }
            }
            else
            {    // Handle regular field.object reference
                if (MetaUtils.isPrimitive(c))
                {
                    mate = MetaUtils.convert(c, jsonObj.get("value"));
                }
                else if (c == Class.class)
                {
                    mate = MetaUtils.classForName((String) jsonObj.get("value"), reader.getClassLoader());
                }
                else if (c.isEnum())
                {
                    mate = getEnum(c, jsonObj);
                }
                else if (Enum.class.isAssignableFrom(c)) // anonymous subclass of an enum
                {
                    mate = getEnum(c.getSuperclass(), jsonObj);
                }
                else if (EnumSet.class.isAssignableFrom(c))
                {
                    mate = getEnumSet(c, jsonObj);
                }
                else if ((mate = coerceCertainTypes(c.getName())) != null)
                {   // if coerceCertainTypes() returns non-null, it did the work
                }
                else
                {
                    mate = newInstance(c, jsonObj);
                }
            }
        }
        else
        {    // @type, not specified, figure out appropriate type
            Object[] items = jsonObj.getArray();

            // if @items is specified, it must be an [] type.
            // if clazz.isArray(), then it must be an [] type.
            if (clazz.isArray() || (items != null && clazz == Object.class && !jsonObj.containsKey("@keys")))
            {
                int size = (items == null) ? 0 : items.length;
                mate = Array.newInstance(clazz.isArray() ? clazz.getComponentType() : Object.class, size);
            }
            else if (clazz.isEnum())
            {
                mate = getEnum(clazz, jsonObj);
            }
            else if (Enum.class.isAssignableFrom(clazz)) // anonymous subclass of an enum
            {
                mate = getEnum(clazz.getSuperclass(), jsonObj);
            }
            else if (EnumSet.class.isAssignableFrom(clazz)) // anonymous subclass of an enum
            {
                mate = getEnumSet(clazz, jsonObj);
            }
            else if ((mate = coerceCertainTypes(clazz.getName())) != null)
            {   // if coerceCertainTypes() returns non-null, it did the work
            }
            else if (clazz == Object.class && !useMapsLocal)
            {
                if (unknownClass == null)
                {
                    mate = new JsonObject();
                    ((JsonObject)mate).type = Map.class.getName();
                }
                else if (unknownClass instanceof String)
                {
                    mate = newInstance(MetaUtils.classForName(((String)unknownClass).trim(), reader.getClassLoader()), jsonObj);
                }
                else
                {
                    throw new JsonIoException("Unable to determine object type at column: " + jsonObj.col + ", line: " + jsonObj.line + ", content: " + jsonObj);
                }
            }
            else
            {
                mate = newInstance(clazz, jsonObj);
            }
        }
        jsonObj.target = mate;
        return jsonObj.target;
    }
This method creates a Java Object instance based on the passed in parameters.
If the JsonObject contains a key '@type' then that is used, as the type was explicitly
set in the JSON stream.  If the key '@type' does not exist, then the passed in Class
is used to create the instance, handling creating an Array or regular Object
instance.
<br>
The '@type' is not often specified in the JSON input stream, as in many
cases it can be inferred from a field reference or array component type.

@param clazz   Instance will be create of this class.
@param jsonObj Map-of-Map representation of object to create.
@return a new Java object of the appropriate type (clazz) using the jsonObj to provide
enough hints to get the right class instantiated.  It is not populated when returned.