src/main/java/com/cedarsoftware/util/io/MapResolver.java
public void traverseFields(final Deque<JsonObject<String, Object>> stack, final JsonObject<String, Object> jsonObj)
    {
        final Object target = jsonObj.target;
        for (Map.Entry<String, Object> e : jsonObj.entrySet())
        {
            final String fieldName = e.getKey();
            final Field field = (target != null) ? MetaUtils.getField(target.getClass(), fieldName) : null;
            final Object rhs = e.getValue();

            if (rhs == null)
            {
                jsonObj.put(fieldName, null);
            }
            else if (rhs == JsonParser.EMPTY_OBJECT)
            {
                jsonObj.put(fieldName, new JsonObject());
            }
            else if (rhs.getClass().isArray())
            {   // RHS is an array
                // Trace the contents of the array (so references inside the array and into the array work)
                JsonObject<String, Object> jsonArray = new JsonObject<String, Object>();
                jsonArray.put("@items", rhs);
                stack.addFirst(jsonArray);

                // Assign the array directly to the Map key (field name)
                jsonObj.put(fieldName, rhs);
            }
            else if (rhs instanceof JsonObject)
            {
                JsonObject<String, Object> jObj = (JsonObject) rhs;

                if (field != null && MetaUtils.isLogicalPrimitive(field.getType()))
                {
                    jObj.put("value", MetaUtils.convert(field.getType(), jObj.get("value")));
                    continue;
                }
                Long refId = jObj.getReferenceId();

                if (refId != null)
                {    // Correct field references
                    JsonObject refObject = getReferencedObj(refId);
                    jsonObj.put(fieldName, refObject);    // Update Map-of-Maps reference
                }
                else
                {
                    stack.addFirst(jObj);
                }
            }
            else if (field != null)
            {   // The code below is 'upgrading' the RHS values in the passed in JsonObject Map
                // by using the @type class name (when specified and exists), to coerce the vanilla
                // JSON values into the proper types defined by the class listed in @type.  This is
                // a cool feature of json-io, that even when reading a map-of-maps JSON file, it will
                // improve the final types of values in the maps RHS, to be of the field type that
                // was optionally specified in @type.
                final Class fieldType = field.getType();
                if (MetaUtils.isPrimitive(fieldType) || BigDecimal.class.equals(fieldType) || BigInteger.class.equals(fieldType) || Date.class.equals(fieldType))
                {
                    jsonObj.put(fieldName, MetaUtils.convert(fieldType, rhs));
                }
                else if (rhs instanceof String)
                {
                    if (fieldType != String.class && fieldType != StringBuilder.class && fieldType != StringBuffer.class)
                    {
                        if ("".equals(((String)rhs).trim()))
                        {   // Allow "" to null out a non-String field on the inbound JSON
                            jsonObj.put(fieldName, null);
                        }
                    }
                }
            }
        }
        jsonObj.target = null;  // don't waste space (used for typed return, not for Map return)
    }
public void traverseFields(final Deque<JsonObject<String, Object>> stack, final JsonObject<String, Object> jsonObj)
    {
        final Object target = jsonObj.target;
        for (Map.Entry<String, Object> e : jsonObj.entrySet())
        {
            final String fieldName = e.getKey();
            final Field field = (target != null) ? MetaUtils.getField(target.getClass(), fieldName) : null;
            final Object rhs = e.getValue();

            if (rhs == null)
            {
                jsonObj.put(fieldName, null);
            }
            else if (rhs == JsonParser.EMPTY_OBJECT)
            {
                jsonObj.put(fieldName, new JsonObject());
            }
            else if (rhs.getClass().isArray())
            {   // RHS is an array
                // Trace the contents of the array (so references inside the array and into the array work)
                JsonObject<String, Object> jsonArray = new JsonObject<String, Object>();
                jsonArray.put("@items", rhs);
                stack.addFirst(jsonArray);

                // Assign the array directly to the Map key (field name)
                jsonObj.put(fieldName, rhs);
            }
            else if (rhs instanceof JsonObject)
            {
                JsonObject<String, Object> jObj = (JsonObject) rhs;

                if (field != null && MetaUtils.isLogicalPrimitive(field.getType()))
                {
                    jObj.put("value", MetaUtils.convert(field.getType(), jObj.get("value")));
                    continue;
                }
                Long refId = jObj.getReferenceId();

                if (refId != null)
                {    // Correct field references
                    JsonObject refObject = getReferencedObj(refId);
                    jsonObj.put(fieldName, refObject);    // Update Map-of-Maps reference
                }
                else
                {
                    stack.addFirst(jObj);
                }
            }
            else if (field != null)
            {   // The code below is 'upgrading' the RHS values in the passed in JsonObject Map
                // by using the @type class name (when specified and exists), to coerce the vanilla
                // JSON values into the proper types defined by the class listed in @type.  This is
                // a cool feature of json-io, that even when reading a map-of-maps JSON file, it will
                // improve the final types of values in the maps RHS, to be of the field type that
                // was optionally specified in @type.
                final Class fieldType = field.getType();
                if (MetaUtils.isPrimitive(fieldType) || BigDecimal.class.equals(fieldType) || BigInteger.class.equals(fieldType) || Date.class.equals(fieldType))
                {
                    jsonObj.put(fieldName, MetaUtils.convert(fieldType, rhs));
                }
                else if (rhs instanceof String)
                {
                    if (fieldType != String.class && fieldType != StringBuilder.class && fieldType != StringBuffer.class)
                    {
                        if ("".equals(((String)rhs).trim()))
                        {   // Allow "" to null out a non-String field on the inbound JSON
                            jsonObj.put(fieldName, null);
                        }
                    }
                }
            }
        }
        jsonObj.target = null;  // don't waste space (used for typed return, not for Map return)
    }
Walk the JsonObject fields and perform necessary substitutions so that all references matched up.
This code patches @ref and @id pairings up, in the 'Map of Map' mode.  Where the JSON may contain
an @id of an object which can have more than one @ref to it, this code will make sure that each
@ref (value side of the Map associated to a given field name) will be pointer to the appropriate Map
instance.
@param stack   Stack (Deque) used for graph traversal.
@param jsonObj a Map-of-Map representation of the current object being examined (containing all fields).