* @param includeSuperclass Boolean indicating if superclass properties should be included in the output JSON.
* @param parsedObjects An array list of objects traversed to try and avoid loops in graphs
* @throws com.granule.json.JSONException Thrown if a JSON conversion error occurs.
*/
private static JSONArtifact introspectBean(Object obj, boolean includeSuperclass, ArrayList parsedObjects) throws JSONException {
JSONObject ja = null;
boolean found = false;
for (int i = 0; i < parsedObjects.size(); i++) {
// Check and try to avoid graphs by parsing the same
// object multiple times, which may indicate a cycle.
Object possibleObj = parsedObjects.get(i);
if (possibleObj != null && obj == possibleObj) {
found = true;
break;
}
}
if (!found) {
parsedObjects.add(obj);
ja = new JSONObject();
Class clazz = obj.getClass();
ja.put("_type", "JavaClass");
ja.put("_classname", clazz.getName());
// Fetch all the methods, based on including superclass or not.
Method[] methods = null;
if (includeSuperclass) {
methods = clazz.getMethods();
} else {
methods = clazz.getDeclaredMethods();
}
if (methods != null && methods.length > 0) {
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
// Include all superclass methods if requested,
// or only those that are part of the actual declaring class.
String mName = m.getName();
Class[] types = m.getParameterTypes();
// Getter, so we can assume this accesses a field.
if (mName.startsWith("get") && mName.length() > 3 && (types == null || types.length == 0)) {
String attr = mName.substring(3, mName.length());
attr = Character.toLowerCase(attr.charAt(0)) + attr.substring(1, attr.length());
try {
Object val = m.invoke(obj, (Object[])null);
if (val == null) {
ja.put(attr, (Object)null);
} else {
Class vClazz = val.getClass();
if (String.class == vClazz) {
ja.put(attr, val);
} else if (Boolean.class == vClazz) {
ja.put(attr, val);
} else if (Class.class == vClazz) {
ja.put(attr, ((Class)val).getName());
} else if (Number.class.isAssignableFrom(vClazz)) {
ja.put(attr, val);
} else if (JSONObject.class.isAssignableFrom(vClazz)) {
ja.put(attr, val);
} else if (JSONArray.class.isAssignableFrom(vClazz)) {
ja.put(attr, val);
} else if (Map.class.isAssignableFrom(vClazz)) {
ja.put(attr, new JSONObject((Map)val));
} else if (Collection.class.isAssignableFrom(vClazz)) {
ja.put(attr, new JSONArray((Collection)obj));
} else {
if (val != obj) {
// Try to avoid processing references to itself.
ja.put(attr, introspectBean(val, includeSuperclass, parsedObjects));
}
}
}
} catch (Exception ex) {
ja.put(attr, (Object)null);
}
}
}
}
}