How to iterate through all properties of a Java bean

15.8k views Asked by At

Below is my bean structure. Employee.java is the parent bean. I would like to iterate through all the properties till the Zip.java and manipulate the values.

I tried to iterate this using reflection, but getDeclaredFields() will give the fields of the top level object only. How to iterate over deeper objects.

Could someone let me know how to do this in java.

Employee.java

private String id;
private String name;
private int age;
private Address addr;
private Contact cont;

Address.java

private String addr1;
private String addr2;
private String city;
private Zip zip;

Contact.java

private String phone;
private String email;

Zip.java

private String zipCd;
private String zipExt;
5

There are 5 answers

0
Massimo On

I did this, but I know and I strongly feel that this is considered bad programming. I did it because someone forced me to, though! (The neatest solution, I think, would've been to write more code... this was the quickest).

public String getNestedDeclaredField(Object obj, String fieldName) {
    if (null == fieldName) {
        return null;
    }
    String[] fieldNames = fieldName.split("\\.");
    Field field = null;
    Class<? extends Object> requestClass = obj.getClass();

    for (String s : fieldNames) {
        try
        {
            field = getSuperClassField(requestClass,
                    requestClass.getSimpleName(), s);
            field.setAccessible(true);
            obj = field.get(obj);

            if (null == obj) {
               return null;
            }
            requestClass = obj.getClass();
        }

        catch (Exception e) {
            log.error("Error while retrieving field {} from {}", s,
                    requestClass.toString(), e);
            return "";
        }
    }

    return obj.toString();
}

public Field getSuperClassField(Class<? extends Object> clazz,
        String clazzName, String fieldName) throws NoSuchFieldException {
    Field field = null;

    try{
        field = clazz.getDeclaredField(fieldName);
    }

    catch (NoSuchFieldException e) {
        clazz = clazz.getSuperclass();

        if (StringUtils.equals(clazz.getSimpleName(), "Object")) {
            log.error("Field {} doesn't seem to appear in class {}",
                    fieldName, clazzName);
            throw new NoSuchFieldException();
        }
        field = getSuperClassField(clazz, clazzName, fieldName);
    }

    catch (Exception e) {
        log.error("Error while retrieving field {} from {}", fieldName,
                clazz.toString(), e);
    }

    return field;
}

Where fieldName is (for zipCd): addr.zip.zipCd

It will retrieve the String value of zipCd from an Employee object.

0
slartidan On

I strongly recommend to use an existing library and to avoid reflection in this case! Use JPA or Hibernate for database uses, use JAXB or similar for JSON/XML/other serialization, etc.

However, if you want to see what an example code would look like you can have a look at this:

package myOwnPackage;
import java.lang.reflect.Field;


class Address {
    private String addr1;
    private String addr2;
    private String city;
    private Zip zip;
}
class Contact {
    private String phone;
    private String email;
}
class Employee {
    private String id;
    private String name;
    private int age;
    private Address addr;
    private Contact cont;

    public void setAddr(Address addr) {
        this.addr = addr;
    }
}

class Zip {
    private String zipCd;
    private String zipExt;
}

public class Main {

    public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {

        Employee employee = new Employee();
        employee.setAddr(new Address());

        printFields("", employee);
    }

    private static void printFields(String prefix, Object container) throws IllegalAccessException {

        Class<? extends Object> class1 = null; 
        Package package1 = null;

        if (container != null)
            class1 = container.getClass();

        if (class1 != null)
            package1 = class1.getPackage();

        if (package1 == null || !"myOwnPackage".equals(package1.getName())) {
            System.out.println(container);
            return;
        }

        for (Field field : class1.getDeclaredFields()) {
            System.out.print(prefix+field.getName()+": ");

            // make private fields accessible
            field.setAccessible(true);

            Object value = field.get(container);
            printFields(prefix+"  ", value);
        }
    }
}

Downsides of my code:

  • This code uses reflection, so you are limited at the depth of fields
  • Inherited fields are not printed
1
Thomas On

You can try this below

First have your POJO's in a inner class and have an arraylist for each POJO type

Public class ModelPojo{

private ArrayList<Employee > employeeList;
private ArrayList<Address> employeeList;
private ArrayList<Zip> employeeList;
private ArrayList<Contact> employeeList;
class Employee {}
class Address{}
class Contact{}
class Zip{}

}

They you can alter your values below way

public class Logic {
someMethod{
ModelPojo.Employee employee ;
        ArrayList<Employee > empList = new ArrayList<Employee >();
        for(int i=0;i<empList .size();i++){
            employee = new ModelPojo(). new Employee ();
            employee .set***("");
            employee .set***("");


            empList .add(product);
        }
}
}

Hope this help

4
NimChimpsky On

getDeclaredFields()

for (Field field : yourObject.getClass().getDeclaredFields()) {
//do stuff
}
1
Razib On

You may use java reflection like this -

for (Field f : Employee.class.getClass().getDeclaredFields()) {

  }