class AbstractExpressionEvaluator implements ExpressionEvaluator {

    protected Object createAndFillObject(ObjectNode json, Object toReturn, String className, List<String> genericClasses) {
        Iterator<Map.Entry<String, JsonNode>> fields = json.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> element = fields.next();
            String key = element.getKey();
            JsonNode jsonNode = element.getValue();
            // if is a simple value just return the parsed result
            if (isSimpleTypeNode(jsonNode)) {
                Map.Entry<String, List<String>> fieldDescriptor = getFieldClassNameAndGenerics(toReturn, key, className, genericClasses);
                Object value = internalLiteralEvaluation(getSimpleTypeNodeTextValue(jsonNode), fieldDescriptor.getKey());
                setField(toReturn, key, value);
                return toReturn;
            }

            if (jsonNode.isArray()) {
                List<Object> nestedList = new ArrayList<>();
                Map.Entry<String, List<String>> fieldDescriptor = getFieldClassNameAndGenerics(toReturn, key, className, genericClasses);
                List<Object> returnedList = createAndFillList((ArrayNode) jsonNode, nestedList, fieldDescriptor.getKey(), fieldDescriptor.getValue());
                setField(toReturn, key, returnedList);
            } else if (jsonNode.isObject()) {
                Map.Entry<String, List<String>> fieldDescriptor = getFieldClassNameAndGenerics(toReturn, key, className, genericClasses);
                Object nestedObject = createObject(fieldDescriptor.getKey(), fieldDescriptor.getValue());
                Object returnedObject = createAndFillObject((ObjectNode) jsonNode, nestedObject, fieldDescriptor.getKey(), fieldDescriptor.getValue());
                setField(toReturn, key, returnedObject);
            } else if (!isEmptyText(jsonNode)) {
                Map.Entry<String, List<String>> fieldDescriptor = getFieldClassNameAndGenerics(toReturn, key, className, genericClasses);
                setField(toReturn, key, internalLiteralEvaluation(jsonNode.textValue(), fieldDescriptor.getKey()));
            } else {
                // empty strings are skipped
            }
        }
        return toReturn;
    }

}