Example usage for java.lang Class getDeclaredMethod

List of usage examples for java.lang Class getDeclaredMethod

Introduction

In this page you can find the example usage for java.lang Class getDeclaredMethod.

Prototype

@CallerSensitive
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
        throws NoSuchMethodException, SecurityException 

Source Link

Document

Returns a Method object that reflects the specified declared method of the class or interface represented by this Class object.

Usage

From source file:com.atlassian.jira.webtests.JIRAWebTest.java

/**
 * This is used to allow access to in-accessible methods by overriding their accessible level to be available
 * publicly. For usage see {@link #getFormElementValue(String, String)}
 *
 * @param subject Object to invoke the method from
 * @param methodName the name of the method to invoke
 * @param methodArgs the actual arguments to pass in to the method call
 * @return output of the method call//from www .j a va2s  .c o m
 */
private Object invoke(Object subject, String methodName, Object[] methodArgs) {
    //determine the argument class types from the actual method arguments
    Class[] params = new Class[methodArgs.length];
    for (int i = 0; i < methodArgs.length; i++) {
        params[i] = methodArgs[i].getClass();
    }

    //look for the method to invoke, if its not in the current class, look in the super class
    Method method = null;
    Class clazz = subject.getClass();
    while (method == null) {
        try {
            method = clazz.getDeclaredMethod(methodName, params);
        } catch (NoSuchMethodException e) {
            clazz = clazz.getSuperclass();
        }
    }
    //override the accessibility to be publicly available
    method.setAccessible(true);
    try {
        return method.invoke(subject, methodArgs);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    } catch (InvocationTargetException e) {
        throw new RuntimeException(e);
    }
}

From source file:ca.oson.json.Oson.java

private <E, R> String object2Serialize(FieldData objectDTO) {
    E obj = (E) objectDTO.valueToProcess;

    Class<R> valueType = objectDTO.returnType;

    if (obj == null) {
        return null;
    }//from  ww  w  . java 2  s .c  om

    // it is possible the same object shared by multiple variables inside the same enclosing object
    int hash = ObjectUtil.hashCode(obj, valueType);
    if (!objectDTO.goAhead(hash)) {
        return "{}";
    }

    ClassMapper classMapper = objectDTO.classMapper;
    // first build up the class-level processing rules
    // || (objectDTO.level == 0 && objectDTO.fieldMapper == null)
    //if (classMapper == null) {
    // 1. Create a blank class mapper instance
    classMapper = new ClassMapper(valueType);

    // 2. Globalize it
    classMapper = globalize(classMapper);
    objectDTO.classMapper = classMapper;
    //}

    if (objectDTO.fieldMapper != null && isInheritMapping()) {
        classMapper = overwriteBy(classMapper, objectDTO.fieldMapper);
    }

    FIELD_NAMING format = getFieldNaming();

    String repeated = getPrettyIndentationln(objectDTO.level), pretty = getPrettySpace();
    objectDTO.incrLevel();
    String repeatedItem = getPrettyIndentationln(objectDTO.level);

    // @Expose
    Set<String> exposed = null;
    if (isUseGsonExpose()) {
        exposed = new HashSet<>();
    }

    boolean annotationSupport = getAnnotationSupport();
    Annotation[] annotations = null;

    if (annotationSupport) {
        annotations = valueType.getAnnotations();

        ca.oson.json.annotation.ClassMapper classMapperAnnotation = null;

        // 3. Apply annotations from other sources
        for (Annotation annotation : annotations) {
            if (ignoreClass(annotation)) {
                return null;
            }

            switch (annotation.annotationType().getName()) {
            case "ca.oson.json.annotation.ClassMapper":
                classMapperAnnotation = (ca.oson.json.annotation.ClassMapper) annotation;
                if (!(classMapperAnnotation.serialize() == BOOLEAN.BOTH
                        || classMapperAnnotation.serialize() == BOOLEAN.TRUE)) {
                    classMapperAnnotation = null;
                }
                break;

            case "ca.oson.json.annotation.ClassMappers":
                ca.oson.json.annotation.ClassMappers classMapperAnnotations = (ca.oson.json.annotation.ClassMappers) annotation;
                for (ca.oson.json.annotation.ClassMapper ann : classMapperAnnotations.value()) {
                    if (ann.serialize() == BOOLEAN.BOTH || ann.serialize() == BOOLEAN.TRUE) {
                        classMapperAnnotation = ann;
                        //break;
                    }
                }
                break;

            case "com.google.gson.annotations.Since":
                Since since = (Since) annotation;
                classMapper.since = since.value();
                break;

            case "com.google.gson.annotations.Until":
                Until until = (Until) annotation;
                classMapper.until = until.value();
                break;

            case "com.fasterxml.jackson.annotation.JsonIgnoreProperties":
                JsonIgnoreProperties jsonIgnoreProperties = (JsonIgnoreProperties) annotation;
                String[] jsonnames = jsonIgnoreProperties.value();
                if (jsonnames != null && jsonnames.length > 0) {
                    if (classMapper.jsonIgnoreProperties == null) {
                        classMapper.jsonIgnoreProperties = new HashSet();
                    }

                    classMapper.jsonIgnoreProperties.addAll(Arrays.asList(jsonnames));
                }
                break;

            case "org.codehaus.jackson.annotate.JsonIgnoreProperties":
                org.codehaus.jackson.annotate.JsonIgnoreProperties jsonIgnoreProperties2 = (org.codehaus.jackson.annotate.JsonIgnoreProperties) annotation;
                String[] jsonnames2 = jsonIgnoreProperties2.value();
                if (jsonnames2 != null && jsonnames2.length > 0) {
                    if (classMapper.jsonIgnoreProperties == null) {
                        classMapper.jsonIgnoreProperties = new HashSet();
                    }

                    classMapper.jsonIgnoreProperties.addAll(Arrays.asList(jsonnames2));
                }
                break;

            case "com.fasterxml.jackson.annotation.JsonPropertyOrder":
                // first come first serve
                if (classMapper.propertyOrders == null) {
                    classMapper.propertyOrders = ((JsonPropertyOrder) annotation).value();
                }
                break;

            case "org.codehaus.jackson.annotate.JsonPropertyOrder":
                // first come first serve
                if (classMapper.propertyOrders == null) {
                    classMapper.propertyOrders = ((org.codehaus.jackson.annotate.JsonPropertyOrder) annotation)
                            .value();
                }
                break;

            case "com.fasterxml.jackson.annotation.JsonInclude":
                if (classMapper.defaultType == JSON_INCLUDE.NONE) {
                    JsonInclude jsonInclude = (JsonInclude) annotation;
                    switch (jsonInclude.content()) {
                    case ALWAYS:
                        classMapper.defaultType = JSON_INCLUDE.ALWAYS;
                        break;
                    case NON_NULL:
                        classMapper.defaultType = JSON_INCLUDE.NON_NULL;
                        break;
                    case NON_ABSENT:
                        classMapper.defaultType = JSON_INCLUDE.NON_NULL;
                        break;
                    case NON_EMPTY:
                        classMapper.defaultType = JSON_INCLUDE.NON_EMPTY;
                        break;
                    case NON_DEFAULT:
                        classMapper.defaultType = JSON_INCLUDE.NON_DEFAULT;
                        break;
                    case USE_DEFAULTS:
                        classMapper.defaultType = JSON_INCLUDE.DEFAULT;
                        break;
                    }
                }
                break;

            case "com.fasterxml.jackson.annotation.JsonAutoDetect":
                JsonAutoDetect jsonAutoDetect = (JsonAutoDetect) annotation;
                if (jsonAutoDetect.fieldVisibility() == Visibility.NONE) {
                    classMapper.useField = false;
                }
                if (jsonAutoDetect.getterVisibility() == Visibility.NONE) {
                    classMapper.useAttribute = false;
                }
                break;

            case "org.codehaus.jackson.annotate.JsonAutoDetect":
                org.codehaus.jackson.annotate.JsonAutoDetect jsonAutoDetect2 = (org.codehaus.jackson.annotate.JsonAutoDetect) annotation;
                if (jsonAutoDetect2
                        .fieldVisibility() == org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE) {
                    classMapper.useField = false;
                }
                if (jsonAutoDetect2
                        .getterVisibility() == org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE) {
                    classMapper.useAttribute = false;
                }

                break;

            case "org.junit.Ignore":
                classMapper.ignore = true;
                break;
            }
        }

        // 4. Apply annotations from Oson
        if (classMapperAnnotation != null) {
            classMapper = overwriteBy(classMapper, classMapperAnnotation);
            exposed = null;
        }

    }

    // 5. Apply Java configuration for this particular class
    ClassMapper javaClassMapper = getClassMapper(valueType);
    if (javaClassMapper != null) {
        classMapper = overwriteBy(classMapper, javaClassMapper);
    }

    // now processing at the class level

    if (classMapper.ignore()) {
        return null;
    }

    if (classMapper.since != null && classMapper.since > getVersion()) {
        return null;
    } else if (classMapper.until != null && classMapper.until <= getVersion()) {
        return null;
    }

    Function function = classMapper.serializer; //getSerializer(valueType);
    if (function == null) {
        function = DeSerializerUtil.getSerializer(valueType.getName());
    }

    if (function != null) {
        try {
            Object returnValue = null;
            if (function instanceof DataMapper2JsonFunction) {
                DataMapper classData = new DataMapper(valueType, obj, classMapper, objectDTO.level,
                        getPrettyIndentation());
                objectDTO.jsonRawValue = false;
                DataMapper2JsonFunction f = (DataMapper2JsonFunction) function;

                return f.apply(classData);

            } else if (function instanceof FieldData2JsonFunction) {
                FieldData2JsonFunction f = (FieldData2JsonFunction) function;
                FieldData fieldData = objectDTO.clone();

                returnValue = f.apply(fieldData);

            } else {
                returnValue = function.apply(obj);
            }

            if (returnValue != null) {
                Class returnType = returnValue.getClass();

                if (returnType == String.class) {
                    return StringUtil.doublequote(returnValue, isEscapeHtml());

                } else if (returnType == valueType || valueType.isAssignableFrom(returnType)) {
                    // just continue to do the serializing
                } else {
                    objectDTO.valueToProcess = returnValue;
                    objectDTO.returnType = returnType;

                    return object2String(objectDTO);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    Set<Class> ignoreFieldsWithAnnotations = classMapper.ignoreFieldsWithAnnotations;

    Map<String, String> keyJsonStrings = new LinkedHashMap<>();
    // to hold relation between name and changed name
    Map<String, String> fieldNames = new LinkedHashMap<>();

    Set<String> processedNameSet = new HashSet<>();
    //StringBuffer sb = new StringBuffer();

    Map<String, Method> getters = null;
    Map<String, Method> setters = null;
    Map<String, Method> otherMethods = null;

    if (valueType.isInterface()) {
        valueType = (Class<R>) obj.getClass();
    } else if (Modifier.isAbstract(valueType.getModifiers())) {
        // valueType

    } else {
        //         Class objClass = obj.getClass();
        //         if (valueType.isAssignableFrom(objClass)) {
        //            valueType = objClass;
        //         }
    }

    //      if (valueType.isInterface()) {
    //         getters = getGetters(obj);
    //         setters = getSetters(obj);
    //         otherMethods = getOtherMethods(obj);
    //      } else {
    getters = getGetters(valueType);
    setters = getSetters(valueType);
    otherMethods = getOtherMethods(valueType);
    //      }

    Set<Method> jsonAnyGetterMethods = new HashSet<>();

    if (classMapper.isToStringAsSerializer()) {
        try {
            Method getter = valueType.getDeclaredMethod("toString", null);

            if (getter != null) {
                E getterValue = ObjectUtil.getMethodValue(obj, getter);

                if (getterValue != null) {
                    Class returnType = getterValue.getClass();

                    if (returnType == String.class) {
                        return StringUtil.doublequote(getterValue, isEscapeHtml());

                    } else if (returnType == valueType || valueType.isAssignableFrom(returnType)) {
                        // just continue to do the serializing
                    } else {
                        objectDTO.valueToProcess = getterValue;
                        objectDTO.returnType = returnType;

                        return object2String(objectDTO);
                    }
                }
            }

        } catch (NoSuchMethodException | SecurityException e) {
            // e.printStackTrace();
        }
    }

    //if (getters != null && getters.size() > 0) {
    boolean isJsonRawValue = false;
    String jsonValueFieldName = DeSerializerUtil.getJsonValueFieldName(valueType.getName());
    //         if (jsonValueFieldName == null) {
    //            // get all fieldmappers for this class?
    //            Set<FieldMapper> fieldMappers = getFieldMappers(valueType);
    //            // looking for the method
    //            for (FieldMapper fieldMapper: fieldMappers) {
    //               if (fieldMapper.jsonValue != null && fieldMapper.jsonValue) {
    //                  jsonValueFieldName = fieldMapper.java;
    //                  isJsonRawValue = fieldMapper.isJsonRawValue();
    //                  break;
    //               }
    //            }
    //         }
    if (jsonValueFieldName == null) {
        jsonValueFieldName = classMapper.getJsonValueFieldName();
    }

    if (jsonValueFieldName != null) {
        String lcjava = jsonValueFieldName.toLowerCase();
        Method getter = null;
        if (getters != null && getters.containsKey(lcjava)) {
            getter = getters.get(lcjava);

        } else {
            try {
                getter = valueType.getMethod(jsonValueFieldName);
            } catch (NoSuchMethodException | SecurityException e) {
                // e.printStackTrace();
            }

            if (getter == null) {
                try {
                    getter = valueType.getMethod("get" + StringUtil.capitalize(jsonValueFieldName));
                } catch (NoSuchMethodException | SecurityException e) {
                    //e.printStackTrace();
                }
            }
        }

        if (getter != null) {
            E getterValue = ObjectUtil.getMethodValue(obj, getter);

            if (getterValue != null) {
                Class returnType = getterValue.getClass();

                if (returnType == String.class) {
                    if (isJsonRawValue) {
                        return getterValue.toString();

                    } else if (StringUtil.parenthesized(getterValue.toString())) {
                        return getterValue.toString();

                    } else {
                        return StringUtil.doublequote(getterValue, isEscapeHtml());
                    }

                } else if (returnType == valueType || valueType.isAssignableFrom(returnType)) {
                    // just continue to do the serializing
                } else {
                    objectDTO.valueToProcess = getterValue;
                    objectDTO.returnType = returnType;
                    objectDTO.jsonRawValue = isJsonRawValue;

                    return object2String(objectDTO);
                }
            }
        }
    }
    //}

    try {
        Field[] fields = null;
        //         if (valueType.isInterface()) {
        //            fields = getFields(obj);
        //         } else {
        fields = getFields(valueType);
        //         }

        for (Field f : fields) {
            f.setAccessible(true);

            String name = f.getName();
            String fieldName = name;
            String lcfieldName = fieldName.toLowerCase();

            if (Modifier.isFinal(f.getModifiers()) && Modifier.isStatic(f.getModifiers())) {
                getters.remove(lcfieldName);
                continue;
            }

            // 6. Create a blank field mapper instance
            FieldMapper fieldMapper = new FieldMapper(name, name, valueType);

            Class<?> returnType = f.getType(); // value.getClass();

            // 7. get the class mapper of returnType
            ClassMapper fieldClassMapper = getClassMapper(returnType);

            // 8. Classify this field mapper with returnType
            fieldMapper = classifyFieldMapper(fieldMapper, fieldClassMapper);

            // 9. Classify this field mapper
            fieldMapper = classifyFieldMapper(fieldMapper, classMapper);

            FieldMapper javaFieldMapper = getFieldMapper(name, null, valueType);

            // getter and setter methods
            Method getter = getters.get(lcfieldName);
            Method setter = setters.get(lcfieldName);

            if (getter != null) {
                getter.setAccessible(true);
            }

            // control by visibility is not always a good idea
            // here consider the visibility of field and related getter method together
            if (ignoreModifiers(f.getModifiers(), classMapper.includeFieldsWithModifiers)) {
                if (getter != null) {
                    if (ignoreModifiers(getter.getModifiers(), classMapper.includeFieldsWithModifiers)) {
                        getters.remove(lcfieldName);
                        continue;
                    }
                } else {
                    continue;
                }
            }

            boolean ignored = false;
            Set<String> names = new HashSet<>();

            if (annotationSupport) {
                annotations = f.getDeclaredAnnotations();//.getAnnotations();

                // field and getter should be treated the same way, if allowed in the class level
                // might not be 100% correct, as the useAttribute as not be applied from annotations yet
                //  && ((javaFieldMapper == null || javaFieldMapper.useAttribute == null) && (fieldMapper.useAttribute == null || fieldMapper.useAttribute))
                // || (javaFieldMapper != null && javaFieldMapper.useAttribute != null && javaFieldMapper.useAttribute)
                // annotations might apply to method only, not the field, so need to get them, regardless using attribute or not
                if (getter != null) {
                    annotations = Stream
                            .concat(Arrays.stream(annotations), Arrays.stream(getter.getDeclaredAnnotations()))
                            .toArray(Annotation[]::new);

                    // no annotations, then try set method
                    if ((annotations == null || annotations.length == 0) && setter != null) {
                        annotations = setter.getDeclaredAnnotations();
                    }
                }

                ca.oson.json.annotation.FieldMapper fieldMapperAnnotation = null;

                for (Annotation annotation : annotations) {
                    if (ignoreField(annotation, ignoreFieldsWithAnnotations)) {
                        ignored = true;
                        break;

                    } else if (annotation instanceof ca.oson.json.annotation.FieldMapper) {
                        fieldMapperAnnotation = (ca.oson.json.annotation.FieldMapper) annotation;
                        if (!(fieldMapperAnnotation.serialize() == BOOLEAN.BOTH
                                || fieldMapperAnnotation.serialize() == BOOLEAN.TRUE)) {
                            fieldMapperAnnotation = null;
                        }

                    } else if (annotation instanceof ca.oson.json.annotation.FieldMappers) {
                        ca.oson.json.annotation.FieldMappers fieldMapperAnnotations = (ca.oson.json.annotation.FieldMappers) annotation;
                        for (ca.oson.json.annotation.FieldMapper ann : fieldMapperAnnotations.value()) {
                            if (ann.serialize() == BOOLEAN.BOTH || ann.serialize() == BOOLEAN.TRUE) {
                                fieldMapperAnnotation = ann;
                                //break;
                            }
                        }

                    } else {
                        // to improve performance, using swith on string
                        switch (annotation.annotationType().getName()) {

                        case "com.fasterxml.jackson.annotation.JsonAnyGetter":
                        case "org.codehaus.jackson.annotate.JsonAnyGetter":
                            fieldMapper.jsonAnyGetter = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonIgnore":
                        case "org.codehaus.jackson.annotate.JsonIgnore":
                            fieldMapper.ignore = true;
                            break;

                        case "javax.persistence.Transient":
                            ignored = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonIgnoreProperties":
                            JsonIgnoreProperties jsonIgnoreProperties = (JsonIgnoreProperties) annotation;
                            if (!jsonIgnoreProperties.allowGetters()) {
                                fieldMapper.ignore = true;
                            } else {
                                fieldMapper.ignore = false;
                                classMapper.jsonIgnoreProperties.remove(name);
                            }
                            break;

                        case "com.google.gson.annotations.Expose":
                            Expose expose = (Expose) annotation;
                            if (!expose.serialize()) {
                                fieldMapper.ignore = true;
                            } else if (exposed != null) {
                                exposed.add(lcfieldName);
                            }
                            break;

                        case "com.google.gson.annotations.Since":
                            Since since = (Since) annotation;
                            fieldMapper.since = since.value();
                            break;

                        case "com.google.gson.annotations.Until":
                            Until until = (Until) annotation;
                            fieldMapper.until = until.value();
                            break;

                        case "com.fasterxml.jackson.annotation.JsonInclude":
                            if (fieldMapper.defaultType == JSON_INCLUDE.NONE) {
                                JsonInclude jsonInclude = (JsonInclude) annotation;

                                switch (jsonInclude.content()) {
                                case ALWAYS:
                                    fieldMapper.defaultType = JSON_INCLUDE.ALWAYS;
                                    break;
                                case NON_NULL:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_NULL;
                                    break;
                                case NON_ABSENT:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_NULL;
                                    break;
                                case NON_EMPTY:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_EMPTY;
                                    break;
                                case NON_DEFAULT:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_DEFAULT;
                                    break;
                                case USE_DEFAULTS:
                                    fieldMapper.defaultType = JSON_INCLUDE.DEFAULT;
                                    break;
                                }
                            }
                            break;

                        case "com.fasterxml.jackson.annotation.JsonRawValue":
                            if (((JsonRawValue) annotation).value()) {
                                fieldMapper.jsonRawValue = true;
                            }
                            break;

                        case "org.codehaus.jackson.annotate.JsonRawValue":
                            if (((org.codehaus.jackson.annotate.JsonRawValue) annotation).value()) {
                                fieldMapper.jsonRawValue = true;
                            }
                            break;

                        case "com.fasterxml.jackson.annotation.JsonValue":
                        case "org.codehaus.jackson.annotate.JsonValue":
                            fieldMapper.jsonValue = true;
                            break;

                        case "org.junit.Ignore":
                            fieldMapper.ignore = true;
                            break;

                        case "javax.persistence.Enumerated":
                            fieldMapper.enumType = ((Enumerated) annotation).value();
                            break;

                        //                  case "javax.persistence.MapKeyEnumerated":
                        //                     mapper.enumType = ((javax.persistence.MapKeyEnumerated) annotation).value();
                        //                     break;

                        case "javax.validation.constraints.NotNull":
                            fieldMapper.required = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonProperty":
                            JsonProperty jsonProperty = (JsonProperty) annotation;
                            Access access = jsonProperty.access();
                            if (access == Access.WRITE_ONLY) {
                                fieldMapper.ignore = true;
                                break;
                            }

                            if (jsonProperty.required()) {
                                fieldMapper.required = true;
                            }

                            if (jsonProperty.defaultValue() != null
                                    && jsonProperty.defaultValue().length() > 0) {
                                fieldMapper.defaultValue = jsonProperty.defaultValue();
                            }
                            break;

                        case "javax.validation.constraints.Size":
                            Size size = (Size) annotation;
                            if (size.min() > 0) {
                                fieldMapper.min = (long) size.min();
                            }
                            if (size.max() < Integer.MAX_VALUE) {
                                fieldMapper.max = (long) size.max();
                            }
                            break;

                        case "javax.persistence.Column":
                            Column column = (Column) annotation;
                            if (column.length() != 255) {
                                fieldMapper.length = column.length();
                            }
                            if (column.scale() > 0) {
                                fieldMapper.scale = column.scale();
                            }

                            if (column.precision() > 0) {
                                fieldMapper.precision = column.precision();
                            }

                            if (!column.nullable()) {
                                fieldMapper.required = true;
                            }

                            break;
                        }

                        String fname = ObjectUtil.getName(annotation);
                        if (!StringUtil.isEmpty(fname)) {
                            names.add(fname);
                        }
                    }
                }

                // 10. Apply annotations from Oson
                // special name to handle
                if (fieldMapperAnnotation != null) {
                    fieldMapper = overwriteBy(fieldMapper, fieldMapperAnnotation, classMapper);
                    exposed = null;
                }
            }

            if (ignored) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            // 11. Apply Java configuration for this particular field
            if (javaFieldMapper != null && javaFieldMapper.isSerializing()) {
                fieldMapper = overwriteBy(fieldMapper, javaFieldMapper);
            }

            if (fieldMapper.ignore != null && fieldMapper.ignore) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            // in the ignored list
            if (ObjectUtil.inSet(name, classMapper.jsonIgnoreProperties)) {
                getters.remove(lcfieldName);
                continue;
            }

            if (fieldMapper.jsonAnyGetter != null && fieldMapper.jsonAnyGetter && getter != null) {
                getters.remove(lcfieldName);
                jsonAnyGetterMethods.add(getter);
                continue;
            }

            if (fieldMapper.useField != null && !fieldMapper.useField) {
                // both should not be used, just like ignore
                if (fieldMapper.useAttribute != null && !fieldMapper.useAttribute) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            if (fieldMapper.since != null && fieldMapper.since > getVersion()) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            } else if (fieldMapper.until != null && fieldMapper.until <= getVersion()) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            //jsonIgnoreProperties

            // handling name now
            boolean jnameFixed = false;
            String json = fieldMapper.json;
            if (StringUtil.isEmpty(json)) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;

            } else if (!json.equals(name)) {
                name = json;
                jnameFixed = true;
            }

            if (!jnameFixed) {
                for (String jsoname : names) {
                    if (!name.equals(jsoname) && !StringUtil.isEmpty(jsoname)) {
                        name = jsoname;
                        jnameFixed = true;
                        break;
                    }
                }
            }

            // only if the name is still the same as the field name
            // format it based on the naming settings
            // otherwise, it is set on purpose
            if (fieldName.equals(name)) {
                name = StringUtil.formatName(name, format);
                jnameFixed = true;
            }

            fieldMapper.java = fieldName;
            fieldMapper.json = name;

            // field valuie
            E value = null;
            try {
                value = (E) f.get(obj);// ObjectUtil.unwraponce(f.get(obj));
            } catch (Exception e) {
            }

            if (value != null) {
                Class vtype = value.getClass();
                if (returnType.isAssignableFrom(vtype)) {
                    returnType = vtype;
                }
            }

            // value from getter
            E getterValue = null;

            if (getter != null) {
                if (fieldMapper.useAttribute == null || fieldMapper.useAttribute) {
                    getterValue = ObjectUtil.getMethodValue(obj, getter);
                    //getterValue = ObjectUtil.unwraponce(getterValue);
                }

                getters.remove(lcfieldName);
            }

            // determine which value to use
            if (getterValue != null) {
                if (getterValue.equals(value) || StringUtil.isEmpty(value)) {
                    value = getterValue;

                } else if (DefaultValue.isDefault(value, returnType)
                        && !DefaultValue.isDefault(getterValue, returnType)) {
                    value = getterValue;
                }
                //               else if (getterValue.toString().length() > value.toString().length()) {
                //                  value = getterValue;
                //               }
            }

            String str;

            FieldData fieldData = new FieldData(obj, f, value, returnType, false, fieldMapper, objectDTO.level,
                    objectDTO.set);

            str = object2Json(fieldData);

            if (fieldMapper.jsonValue != null && fieldMapper.jsonValue) {
                if (fieldMapper.isJsonRawValue()) {
                    return StringUtil.unquote(str, isEscapeHtml());
                } else {
                    return StringUtil.doublequote(str, isEscapeHtml());
                }
            }

            if (StringUtil.isNull(str)) {
                if (fieldMapper.defaultType == JSON_INCLUDE.NON_NULL
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                    continue;

                } else {
                    str = "null";
                }

            } else if (StringUtil.isEmpty(str)) {
                if (fieldMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                    continue;
                }

                str = "\"\"";

            } else if (fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT
                    && DefaultValue.isDefault(str, returnType)) {
                continue;
            }

            StringBuffer sb = new StringBuffer();
            sb.append(repeatedItem);
            if (fieldMapper.jsonNoName == null || !fieldMapper.jsonNoName) {
                sb.append("\"" + name + "\":" + pretty);
            }
            sb.append(str);
            sb.append(",");

            keyJsonStrings.put(lcfieldName, sb.toString());
            processedNameSet.add(name);
            fieldNames.put(lcfieldName, name.toLowerCase());
        }

        // now process get methods
        for (Entry<String, Method> entry : getters.entrySet()) {
            String lcfieldName = entry.getKey();
            Method getter = entry.getValue();

            if (ignoreModifiers(getter.getModifiers(), classMapper.includeFieldsWithModifiers)) {
                continue;
            }
            if (Modifier.isFinal(getter.getModifiers()) && Modifier.isStatic(getter.getModifiers())) {
                continue;
            }

            String name = getter.getName();
            if (name.substring(3).equalsIgnoreCase(lcfieldName)) {
                name = StringUtil.uncapitalize(name.substring(3));
            }

            // just use field name, even it might not be a field
            String fieldName = name;

            if (processedNameSet.contains(name) || fieldNames.containsKey(lcfieldName)) {
                continue;
            }

            getter.setAccessible(true);

            Method setter = setters.get(lcfieldName);

            // 6. Create a blank field mapper instance
            FieldMapper fieldMapper = new FieldMapper(name, name, valueType);

            Class<?> returnType = getter.getReturnType();

            // 7. get the class mapper of returnType
            ClassMapper fieldClassMapper = getClassMapper(returnType);

            // 8. Classify this field mapper with returnType
            fieldMapper = classifyFieldMapper(fieldMapper, fieldClassMapper);

            // 9. Classify this field mapper
            fieldMapper = classifyFieldMapper(fieldMapper, classMapper);

            FieldMapper javaFieldMapper = getFieldMapper(name, null, valueType);

            boolean ignored = false;
            Set<String> names = new HashSet<>();

            if (annotationSupport) {
                annotations = getter.getDeclaredAnnotations();//.getAnnotations();

                // no annotations, then try set method
                if ((annotations == null || annotations.length == 0) && setter != null) {
                    annotations = setter.getDeclaredAnnotations();
                }

                ca.oson.json.annotation.FieldMapper fieldMapperAnnotation = null;

                for (Annotation annotation : annotations) {
                    if (ignoreField(annotation, ignoreFieldsWithAnnotations)) {
                        ignored = true;
                        break;

                    } else if (annotation instanceof ca.oson.json.annotation.FieldMapper) {
                        fieldMapperAnnotation = (ca.oson.json.annotation.FieldMapper) annotation;
                        if (!(fieldMapperAnnotation.serialize() == BOOLEAN.BOTH
                                || fieldMapperAnnotation.serialize() == BOOLEAN.TRUE)) {
                            fieldMapperAnnotation = null;
                        }

                    } else if (annotation instanceof ca.oson.json.annotation.FieldMappers) {
                        ca.oson.json.annotation.FieldMappers fieldMapperAnnotations = (ca.oson.json.annotation.FieldMappers) annotation;
                        for (ca.oson.json.annotation.FieldMapper ann : fieldMapperAnnotations.value()) {
                            if (ann.serialize() == BOOLEAN.BOTH || ann.serialize() == BOOLEAN.TRUE) {
                                fieldMapperAnnotation = ann;
                                //break;
                            }
                        }

                    } else {
                        // to improve performance, using swith on string
                        switch (annotation.annotationType().getName()) {
                        case "com.fasterxml.jackson.annotation.JsonAnyGetter":
                        case "org.codehaus.jackson.annotate.JsonAnyGetter":
                            fieldMapper.jsonAnyGetter = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonIgnore":
                        case "org.codehaus.jackson.annotate.JsonIgnore":
                            fieldMapper.ignore = true;
                            break;

                        case "javax.persistence.Transient":
                            ignored = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonIgnoreProperties":
                            JsonIgnoreProperties jsonIgnoreProperties = (JsonIgnoreProperties) annotation;
                            if (!jsonIgnoreProperties.allowGetters()) {
                                fieldMapper.ignore = true;
                            } else {
                                fieldMapper.ignore = false;
                                classMapper.jsonIgnoreProperties.remove(name);
                            }
                            break;

                        case "com.google.gson.annotations.Expose":
                            Expose expose = (Expose) annotation;
                            if (!expose.serialize()) {
                                fieldMapper.ignore = true;
                            } else if (exposed != null) {
                                exposed.add(lcfieldName);
                            }
                            break;

                        case "com.google.gson.annotations.Since":
                            Since since = (Since) annotation;
                            fieldMapper.since = since.value();
                            break;

                        case "com.google.gson.annotations.Until":
                            Until until = (Until) annotation;
                            fieldMapper.until = until.value();
                            break;

                        case "com.fasterxml.jackson.annotation.JsonInclude":
                            if (fieldMapper.defaultType == JSON_INCLUDE.NONE) {
                                JsonInclude jsonInclude = (JsonInclude) annotation;

                                switch (jsonInclude.content()) {
                                case ALWAYS:
                                    fieldMapper.defaultType = JSON_INCLUDE.ALWAYS;
                                    break;
                                case NON_NULL:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_NULL;
                                    break;
                                case NON_ABSENT:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_NULL;
                                    break;
                                case NON_EMPTY:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_EMPTY;
                                    break;
                                case NON_DEFAULT:
                                    fieldMapper.defaultType = JSON_INCLUDE.NON_DEFAULT;
                                    break;
                                case USE_DEFAULTS:
                                    fieldMapper.defaultType = JSON_INCLUDE.DEFAULT;
                                    break;
                                }
                            }
                            break;

                        case "com.fasterxml.jackson.annotation.JsonRawValue":
                            if (((JsonRawValue) annotation).value()) {
                                fieldMapper.jsonRawValue = true;
                            }
                            break;

                        case "org.codehaus.jackson.annotate.JsonRawValue":
                            if (((org.codehaus.jackson.annotate.JsonRawValue) annotation).value()) {
                                fieldMapper.jsonRawValue = true;
                            }
                            break;

                        case "com.fasterxml.jackson.annotation.JsonValue":
                        case "org.codehaus.jackson.annotate.JsonValue":
                            fieldMapper.jsonValue = true;
                            break;

                        case "javax.persistence.Enumerated":
                            fieldMapper.enumType = ((Enumerated) annotation).value();
                            break;

                        //                  case "javax.persistence.MapKeyEnumerated":
                        //                     mapper.enumType = ((javax.persistence.MapKeyEnumerated) annotation).value();
                        //                     break;

                        case "javax.validation.constraints.NotNull":
                            fieldMapper.required = true;
                            break;

                        case "com.fasterxml.jackson.annotation.JsonProperty":
                            JsonProperty jsonProperty = (JsonProperty) annotation;
                            Access access = jsonProperty.access();
                            if (access == Access.WRITE_ONLY) {
                                fieldMapper.ignore = true;
                                break;
                            }

                            if (jsonProperty.required()) {
                                fieldMapper.required = true;
                            }

                            if (jsonProperty.defaultValue() != null
                                    && jsonProperty.defaultValue().length() > 0) {
                                fieldMapper.defaultValue = jsonProperty.defaultValue();
                            }
                            break;

                        case "org.junit.Ignore":
                            fieldMapper.ignore = true;
                            break;

                        case "javax.validation.constraints.Size":
                            Size size = (Size) annotation;
                            if (size.min() > 0) {
                                fieldMapper.min = (long) size.min();
                            }
                            if (size.max() < Integer.MAX_VALUE) {
                                fieldMapper.max = (long) size.max();
                            }
                            break;

                        case "javax.persistence.Column":
                            Column column = (Column) annotation;
                            if (column.length() != 255) {
                                fieldMapper.length = column.length();
                            }
                            if (column.scale() > 0) {
                                fieldMapper.scale = column.scale();
                            }

                            if (column.precision() > 0) {
                                fieldMapper.precision = column.precision();
                            }

                            if (!column.nullable()) {
                                fieldMapper.required = true;
                            }

                            break;
                        }

                        String fname = ObjectUtil.getName(annotation);
                        if (fname != null) {
                            names.add(fname);
                        }
                    }
                }

                // 10. Apply annotations from Oson
                // special name to handle
                if (fieldMapperAnnotation != null) {
                    fieldMapper = overwriteBy(fieldMapper, fieldMapperAnnotation, classMapper);
                    exposed = null;
                }
            }

            if (ignored) {
                continue;
            }

            // 11. Apply Java configuration for this particular field
            if (javaFieldMapper != null && javaFieldMapper.isSerializing()) {
                fieldMapper = overwriteBy(fieldMapper, javaFieldMapper);
            }

            if (fieldMapper.ignore != null && fieldMapper.ignore) {
                continue;
            }

            // in the ignored list
            if (ObjectUtil.inSet(name, classMapper.jsonIgnoreProperties)) {
                continue;
            }

            if (fieldMapper.jsonAnyGetter != null && fieldMapper.jsonAnyGetter) {
                jsonAnyGetterMethods.add(getter);
                continue;
            }

            if (fieldMapper.useAttribute != null && !fieldMapper.useAttribute) {
                continue;
            }

            if (fieldMapper.since != null && fieldMapper.since > getVersion()) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            } else if (fieldMapper.until != null && fieldMapper.until <= getVersion()) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;
            }

            // handling name now
            boolean jnameFixed = false;
            String json = fieldMapper.json;
            if (StringUtil.isEmpty(json)) {
                if (getter != null) {
                    getters.remove(lcfieldName);
                }
                continue;

            } else if (!json.equals(name)) {
                name = json;
                jnameFixed = true;
            }

            if (!jnameFixed) {
                for (String jsoname : names) {
                    if (!name.equals(jsoname) && !StringUtil.isEmpty(jsoname)) {
                        name = jsoname;
                        jnameFixed = true;
                        break;
                    }
                }
            }

            // only if the name is still the same as the field name
            // format it based on the naming settings
            // otherwise, it is set on purpose
            if (fieldName.equals(name)) {
                name = StringUtil.formatName(name, format);
                jnameFixed = true;
            }

            fieldMapper.java = fieldName;
            fieldMapper.json = name;

            // get value
            E value = ObjectUtil.getMethodValue(obj, getter);

            if (fieldMapper.jsonValue != null && fieldMapper.jsonValue) {
                if (value != null) {
                    if (fieldMapper.isJsonRawValue()) {
                        return value.toString();
                    } else {
                        return StringUtil.doublequote(value, isEscapeHtml());
                    }
                }
            }

            if (returnType == Class.class) {
                if (value != null && returnType != value.getClass()) {
                    returnType = value.getClass();
                } else {
                    continue;
                }
            }

            String str = null;

            //if (returnType != valueType) {
            FieldData fieldData = new FieldData(obj, null, value, returnType, false, fieldMapper,
                    objectDTO.level, objectDTO.set);
            objectDTO.getter = getter;
            str = object2Json(fieldData);
            //}

            if (StringUtil.isNull(str)) {
                if (fieldMapper.defaultType == JSON_INCLUDE.NON_NULL
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                    continue;

                } else {
                    str = "null";
                }

            } else if (StringUtil.isEmpty(str)) {
                if (fieldMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                        || fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                    continue;
                }

                str = "null";

            } else if (fieldMapper.defaultType == JSON_INCLUDE.NON_DEFAULT
                    && DefaultValue.isDefault(str, returnType)) {
                continue;
            }

            StringBuffer sb = new StringBuffer();
            sb.append(repeatedItem);
            if (fieldMapper.jsonNoName == null || !fieldMapper.jsonNoName) {
                sb.append("\"" + name + "\":" + pretty);
            }
            sb.append(str);
            sb.append(",");

            keyJsonStrings.put(lcfieldName, sb.toString());
            processedNameSet.add(name);
            fieldNames.put(lcfieldName, name.toLowerCase());
        }

        // handle @JsonAnyGetter
        if (annotationSupport) {
            for (Entry<String, Method> entry : otherMethods.entrySet()) {
                Method method = entry.getValue();
                if (ignoreModifiers(method.getModifiers(), classMapper.includeFieldsWithModifiers)) {
                    continue;
                }

                for (Annotation annotation : method.getAnnotations()) {
                    if (ignoreField(annotation, ignoreFieldsWithAnnotations)) {
                        continue;
                    }

                    if (annotation instanceof JsonValue
                            || annotation instanceof org.codehaus.jackson.annotate.JsonValue) {
                        Object mvalue = ObjectUtil.getMethodValue(obj, method);
                        if (mvalue != null) {
                            return StringUtil.doublequote(mvalue, isEscapeHtml());
                        }

                    } else if (annotation instanceof JsonAnyGetter
                            || annotation instanceof org.codehaus.jackson.annotate.JsonAnyGetter
                            || annotation instanceof ca.oson.json.annotation.FieldMapper) {

                        if (annotation instanceof ca.oson.json.annotation.FieldMapper) {
                            ca.oson.json.annotation.FieldMapper fieldMapper = (ca.oson.json.annotation.FieldMapper) annotation;

                            if (fieldMapper.jsonAnyGetter() == BOOLEAN.FALSE) {
                                continue;
                            }
                        }

                        jsonAnyGetterMethods.add(method);
                    }
                }
            }
        }

        for (Method method : jsonAnyGetterMethods) {
            if (method != null) {
                Object allValues = ObjectUtil.getMethodValue(obj, method);

                if (allValues != null && allValues instanceof Map) {
                    Map<String, Object> map = (Map) allValues;
                    String str;
                    for (String name : map.keySet()) {
                        Object value = map.get(name);

                        // java to json, check if this name is allowed or changed
                        name = java2Json(name);

                        if (!StringUtil.isEmpty(name)) {

                            FieldData newFieldData = new FieldData(value, value.getClass(), false,
                                    objectDTO.level, objectDTO.set);
                            newFieldData.defaultType = classMapper.defaultType;
                            str = object2Json(newFieldData);

                            if (StringUtil.isNull(str)) {
                                if (classMapper.defaultType == JSON_INCLUDE.NON_NULL
                                        || classMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                                        || classMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                                    continue;

                                } else {
                                    str = "null";
                                }

                            } else if (StringUtil.isEmpty(str)) {
                                if (classMapper.defaultType == JSON_INCLUDE.NON_EMPTY
                                        || classMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                                    continue;
                                }

                                str = "null";

                            } else if (DefaultValue.isDefault(str, value.getClass())) {
                                if (classMapper.defaultType == JSON_INCLUDE.NON_DEFAULT) {
                                    continue;
                                }
                            }

                            StringBuffer sb = new StringBuffer();
                            sb.append(repeatedItem);
                            sb.append("\"" + name + "\":" + pretty);
                            sb.append(str);
                            sb.append(",");
                            keyJsonStrings.put(name, sb.toString());
                        }
                    }
                }
            }
        }

        int size = keyJsonStrings.size();
        if (size == 0) {
            return "{}"; // ""

        } else {
            String includeClassType = "";
            if (classMapper.includeClassTypeInJson) { //getIncludeClassTypeInJson()
                includeClassType = repeatedItem + "\"@class\":" + pretty + "\"" + valueType.getName() + "\",";
            }

            if (exposed != null && exposed.size() > 0) {
                Map<String, String> map = new LinkedHashMap<>();

                for (String key : keyJsonStrings.keySet()) {
                    if (exposed.contains(key)) {
                        map.put(key, keyJsonStrings.get(key));
                    }
                }

                keyJsonStrings = map;
            }

            if (keyJsonStrings.size() == 1 && this.isValueOnly()) {
                for (Map.Entry<String, String> entry : keyJsonStrings.entrySet()) {
                    if (entry.getKey().toLowerCase().equals("value")) {
                        String value = entry.getValue();
                        String[] values = value.split(":");
                        value = null;
                        if (values.length == 1) {
                            value = values[0];
                        } else if (values.length == 2) {
                            value = values[1];
                        }
                        if (value != null && value.length() > 1) {
                            return value.substring(0, value.length() - 1);
                        }
                    }
                }
            }

            // based on sorting requirements
            StringBuffer sb = new StringBuffer();
            if (classMapper.propertyOrders != null) {
                for (String property : classMapper.propertyOrders) {
                    property = property.toLowerCase();
                    String jsonText = keyJsonStrings.get(property);
                    if (jsonText != null) {
                        sb.append(jsonText);
                        keyJsonStrings.remove(property);
                    } else {
                        property = fieldNames.get(property);
                        if (property != null && keyJsonStrings.containsKey(property)) {
                            sb.append(keyJsonStrings.get(property));
                            keyJsonStrings.remove(property);
                        }
                    }
                }
            }

            List<String> properties = new ArrayList(keyJsonStrings.keySet());
            if (classMapper.orderByKeyAndProperties) {
                Collections.sort(properties);
            }

            for (String property : properties) {
                sb.append(keyJsonStrings.get(property));
            }

            String text = sb.toString();
            size = text.length();
            if (size == 0) {
                return "{}";
            } else {
                return "{" + includeClassType + text.substring(0, size - 1) + repeated + "}";
            }
        }

    } catch (IllegalArgumentException | SecurityException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
        // } catch (InvocationTargetException e) {
    }
}