So I'm writing an "POJO to JSON" converter. I want to be able to pass in a List<T>
object and convert to JSON.
Hopefully this will make sense
/**
*
* 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 "[]";
}
}
When I get to the Object obj
section, my obj
is correct. I can debug it and see the name and value of the class.
Let's say that class is this:
public class User {
private firstName;
private lastName;
... getters....setters....etc...
}
So that now, obj
is a Site.
OK, I then try to get the field names (firstName, lastName) but the fields object is empty.
What am I doing wrong?
Thanks
EDIT
I got it to work! This is not finished code, but it's doing exactly what I want for now. I've read that Google and Jackson will do this too. If someone can provide a good link on how to selectively pick properties from a POJO, then I'm all ears.
Or better yet, I'd like to know WHY I shouldn't be doing this, this way?
Thanks!
Jsonator (NOT FINISHED)
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 "[]";
}
}
Site Class
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;
}
}
EXAMPLE
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();
}
}
}
UPDATE 2
Here is the better Jsonator
for those interested:
https://gist.github.com/3893242
You can pass in an "exclude" String[] and it will not include those. Plus, it has a standard "results, message, etc" that we like to pass back in our AJAX requests. Good for ExtJS.
We can use newInstance() method on the constructor object to instantiate a new instance of the class. Since we use reflection when we don't have the classes information at compile time, we can assign it to Object and then further use reflection to access it's fields and invoke it's methods.
In order to reflect a Java class, we first need to create an object of Class . And, using the object we can call various methods to get information about methods, fields, and constructors present in a class. class Dog {...} // create object of Class // to reflect the Dog class Class a = Class. forName("Dog");
By using Java reflection, we are also able to get information about the package of any class or object. This data is bundled inside the Package class, which is returned by a call to getPackage method on the class object.
Java Reflection makes it possible to inspect classes, interfaces, fields and methods at runtime, without knowing the names of the classes, methods etc. at compile time. It is also possible to instantiate new objects, invoke methods and get/set field values using reflection.
Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program. For example, it's possible for a Java class to obtain the names of all its members and display them.
You need to use #getDeclaredFields()
to include private fields, #getFields()
only lists the public ones.
With private
fields you will also run into access restriction problems, so you probably want to look into the Field#setAccessible()
method as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With