Reputation: 28555
Is this possible? I am creating a an object from a JSON string with this code:
String obj = new Gson().toJson(jsonArray.getJSONObject(i));
String className = getClassName(jsonArray.getJSONObject(i));
Class targetClass = null;
try {
targetClass = Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//Create Object
Object data = new Gson().fromJson(obj, targetClass);
I then do some database stuff, get a return key value and I want to set that key on the bean object using its setId() setter, but I don't want to have to cast the specific type of object to the generic object because that would require my repeating the exact same code many times just to cast the object.
key = contactsListDAO.manageDataObj(data, sql, true);
((PhoneNumber) data).setId(key);
Can I use some sort of if statement to check if the object contains an id property and then set the id on the generic object without having to cast?
Upvotes: 0
Views: 3283
Reputation: 28555
Here is my working code. For some reason I could never find the method using class.getMethod() so I had to loop through an array of methods and match the names to the setId method that I knew existed. From there using invoke was the key to setting the property correctly.
public void setIdOnObject(Object obj, int id, Class<?> targetClass) {
Method[] methods = targetClass.getMethods();
for(Method i : methods) {
if(i.getName().equals("setId")) {
try {
i.invoke(obj, id);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
Upvotes: 1
Reputation: 28608
reflection can do that but I think maybe here you should do something else. Write a utility function
public static <T> T fromJson(String json, Class<T> clzz)
{
return (T) new Gson().fromJson(obj, targetClass);
}
and then you can call it like so
PhoneNumber data = fromJson(obj, PhoneNumber.class);
no more conversion.
EDIT : if using "Object" is a constraint you can use reflection
public void setIdOnObject(Object obj, Object id)
{
try{
Method m = obj.getClass().getMethod("setId",id.getClass());
m.invoke(obj, id );
}catch(NoSuchMethodException e){ return false; } catch (InvocationTargetException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (IllegalAccessException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
Here is a working example I have, just copy-paste-run.
import java.lang.reflect.InvocationTargetException;
public class Reflection
{
public static void main( String[] args )
{
MyParent p = new MyParent();
setParentKey( p, "parentKey" );
MyObj o = new MyObj();
setParentKey( o, "myParentKey" );
setMyKey( o, "myKey" );
System.out.println( "p = " + p );
System.out.println( "o = " + o );
}
public static void invokeMethod( Object p, Object k, String methodName )
{
try
{
p.getClass().getMethod( methodName, k.getClass() ).invoke( p, k );
}
catch ( NoSuchMethodException e )
{
e.printStackTrace();
}
catch ( InvocationTargetException e )
{
e.printStackTrace();
}
catch ( IllegalAccessException e )
{
e.printStackTrace();
}
}
public static void setParentKey( Object p, Object k )
{
invokeMethod( p,k,"setParentKey" );
}
public static void setMyKey( Object p, Object k )
{
invokeMethod( p,k,"setMyKey" );
}
public static class MyParent
{
private Object parentKey;
public void setParentKey( String k )
{
parentKey = k;
}
@Override
public String toString()
{
return "MyParent{" +
"parentKey=" + parentKey +
'}';
}
}
public static class MyObj extends MyParent
{
private Object myKey;
public void setMyKey( String k )
{
myKey = k;
}
@Override
public String toString()
{
return "MyObj{" +
"myKey=" + myKey +
"} " + super.toString();
}
}
}
And the expected output is :
p = MyParent{parentKey=parentKey}
o = MyObj{myKey=myKey} MyParent{parentKey=myParentKey}
Upvotes: 0
Reputation: 42461
If you have (as you mention) "multiple bean types" and "they all have an id property", why don't you define a common interface for you beans with a setId method?
You'll get your beans and just cast to the interface which will be a safe and object-oriented approach. Is it a viable solution for you?
Upvotes: 0