¿Cómo se puede usar la reflexión para obtener los nombres y valores de propiedades de un POJO?

Así que estoy escribiendo un convertidor de "POJO a JSON". Quiero poder pasar en unList<T> objeto y convertir a JSON.

Esperemos que esto tenga sentido

/**
 *
     * NOT COMPLETE!!!  OBVIOUSLY!!!
 */
public abstract class Jsonator<T> implements Serializable {

    private Class<T> entityClass;
    private JSONObject json;
    private JSONArray jsonArray;

    public Jsonator(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    public void convert(List<T> paObjectList) throws IllegalArgumentException, IllegalAccessException {
        json = new JSONObject();
        jsonArray = new JSONArray();

        try {

            for (Object obj : paObjectList) {
                JSONObject objJson = new JSONObject();

                Class<?> kls = obj.getClass();

                Field[] fields = kls.getFields();
                for (Field field : fields) {
                    objJson.put(field.getName(), (T) field.get(obj));
                }

                jsonArray.add(objJson);
            }

            json.put("results", jsonArray);

        }
        catch (Exception ex) {
        }
    }

    public String error() {
        return "ERROR";
    }

    public String results() {
        if (json != null) {
            return json.toJSONString();
        }

        return "[]";
    }
}

Cuando llego a laObject obj sección, miobj es correcto. Puedo depurarlo y ver el nombre y el valor de la clase.

Digamos que la clase es esta:

public class User {
    private firstName;
    private lastName;

    ... getters....setters....etc...

}

Así que ahora,obj es un sitio OK, luego trato de obtener los nombres de los campos (nombre, apellido) pero el objeto de los campos está vacío.

¿Qué estoy haciendo mal?

Gracias

EDITAR

¡Yo tengo que trabajar! Este no es un código terminado, pero está haciendo exactamente lo que quiero por ahora. He leído que Google y Jackson también lo harán. Si alguien puede proporcionar un buen enlace sobre cómo elegir propiedades de forma selectiva desde un POJO, entonces soy todo oídos.

O mejor aún, me gustaría saber.POR QUÉ ¿No debería estar haciendo esto, de esta manera?

¡Gracias!

Jsonator (NO TERMINADO)

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

/**
 *
 * @author Cecil.Meeks
 */
public abstract class Jsonator<T> implements Serializable {

    private Class<T> entityClass;
    private JSONObject json;
    private JSONArray jsonArray;

    public Jsonator(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    public void convert(List<T> paObjectList) throws IllegalArgumentException, IllegalAccessException {
        json = new JSONObject();
        jsonArray = new JSONArray();

        try {

            for (Object obj : paObjectList) {
                JSONObject objJson = new JSONObject();

                Class<?> kls = obj.getClass();

                Field[] fields = kls.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    objJson.put(field.getName(), field.get(obj));
                }

                jsonArray.add(objJson);
            }

            json.put("results", jsonArray);

        }
        catch (SecurityException ex) {
            ex.printStackTrace();
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public String error() {
        return "ERROR";
    }

    public String results() {
        if (json != null) {
            return json.toJSONString();
        }

        return "[]";
    }
}

Clase de sitio

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;

@Entity
@Table(name = "Sites")
public class Site implements Serializable {

    private String siteKey;
    private String site;
    private String siteType;
    private String address1;
    private String address2;
    private String city;
    private String zipCode;
    private String createdBy;
    private String glCode;

    public Site() {
    }

    @Id
    @GenericGenerator(name = "generator", strategy = "guid", parameters = {})
    @GeneratedValue(generator = "generator")
    public String getSiteKey() {
        return siteKey;
    }

    public void setSiteKey(String siteKey) {
        this.siteKey = siteKey;
    }

    @Column(name = "Site", unique = true, length = 125, nullable = false)
    public String getSite() {
        return site;
    }

    public void setSite(String site) {
        this.site = site;
    }

    @Column(name = "SiteType", unique = false, length = 8, nullable = true)
    public String getSiteType() {
        return siteType;
    }

    public void setSiteType(String siteType) {
        this.siteType = siteType;
    }

    @Column(name = "Address1", unique = false, length = 125, nullable = true)
    public String getAddress1() {
        return address1;
    }

    public void setAddress1(String address1) {
        this.address1 = address1;
    }

    @Column(name = "Address2", unique = false, length = 125, nullable = true)
    public String getAddress2() {
        return address2;
    }

    public void setAddress2(String address2) {
        this.address2 = address2;
    }

    @Column(name = "City", unique = false, length = 125, nullable = true)
    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Column(name = "ZipCode", unique = false, length = 50, nullable = true)
    public String getZipCode() {
        return zipCode;
    }

    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }

    @Column(name = "CreatedBy", unique = false, length = 125, nullable = true)
    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    @Column(name = "GLCode", unique = false, length = 11, nullable = true)
    public String getGlCode() {
        return glCode;
    }

    public void setGlCode(String glCode) {
        this.glCode = glCode;
    }


}

EJEMPLO

public class SiteJsonator extends Jsonator<Site> {

    public SiteJsonator() {
        super(Site.class);
    }

}

@Controller
@RequestMapping(value = "/sites")
public class SitesController {

    @Autowired
    private SiteService siteService;

    @RequestMapping(value = "/", method = RequestMethod.GET, headers = "Accept=application/json")
    @ResponseBody
    public String index(ModelMap map) {

        SiteJsonator list  = new SiteJsonator();;
        try {
            list.convert(siteService.getAll());
            return list.results();
        }
        catch (Exception ex) {
            return list.error();
        } 
    }
}

ACTUALIZACIÓN 2

Aquí está el mejorJsonator para los interesados:

https://gist.github.com/3893242

Puede pasar una cadena "excluir" [] y no la incluirá. Además, tiene un "resultado, mensaje, etc." estándar que nos gusta devolver a nuestras solicitudes AJAX. Bueno para ExtJS.

Respuestas a la pregunta(2)

Su respuesta a la pregunta