Reputation: 177
I was given a class (which I could not change) with a lot of fields of String, each of them have a set method.
public class C {
private String fieldA,
private String fieldB,
...
public void setFieldA(String s) {
this.fieldA = s;
}
public void setFieldB(String s) {
this.fieldB = s;
}
...
}
I need to write code to create an instance of the class and initialize it with a json object (which will have value for some or all of the fields).
The json is very simple and looks like:
{"fieldA":"valueA", "fieldB":"valueB"..... }
I know I could write something like below for every field:
if (myJsonObj.containsKey("fieldA"){
myInstance.setFieldA(myJsonObj.get("fieldA").toString());
}
I'm wondering if there is a smarter way I could do this, since the number of fields could be up to about thirty. Instead of repeating the above code thirty times (and the only thing different between each is "fieldA" in the above code).
Thanks!
Upvotes: 0
Views: 79
Reputation: 177
Thanks to Chris Parker. Here is my final code based on his original code. Because there are many String fields in the class and it might change in the future, so using reflect makes the update/change very easy: I only need to change the String Array.
The given class is like below (only String fields and their set methods are shown):
public class MyClass {
private String fieldA,
private String fieldB,
...
public void setFieldA(String s) {
this.fieldA = s;
}
public void setFieldB(String s) {
this.fieldB = s;
}
...
}
The method to set the value of those string fields using a JSONObject input to an instance of C:
public void fillClassStringFields(MyClass c, JSONObject input) {
String[] names = {"FieldA","FieldB",...};
Class<MyClass> clazz = MyClass.class;
Class<?>[] types = {String.class};
for(int i = 0; i< names.length;i++) {
String name = names[i].toString();
String methodName = "set" + name;
if(input.containsKey(name)) {
try {
Method method = clazz.getDeclaredMethod(methodName, types);
method.invoke(c, input.get(name).toString());
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
Upvotes: 0
Reputation: 426
Sounds like a job for reflection to me. Everything except the bit marked with "Reflection" is here solely to make this an SSCCE. You'll likely have your own way to track which methods are available or whatever. Take a look at the following site for an (IMHO) excellent guide (I am not affiliated with the site in any way): Guide to Java Reflection
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Test {
private String fieldA;
private String fieldB;
private String fieldC;
private String fieldD;
private String fieldE;
public String getFieldA() {
return fieldA;
}
public void setFieldA(final String fieldA) {
this.fieldA = fieldA;
}
public String getFieldB() {
return fieldB;
}
public void setFieldB(final String fieldB) {
this.fieldB = fieldB;
}
public String getFieldC() {
return fieldC;
}
public void setFieldC(final String fieldC) {
this.fieldC = fieldC;
}
public String getFieldD() {
return fieldD;
}
public void setFieldD(final String fieldD) {
this.fieldD = fieldD;
}
public String getFieldE() {
return fieldE;
}
public void setFieldE(final String fieldE) {
this.fieldE = fieldE;
}
private static final char[] chars = {'A', 'B', 'C', 'D', 'E'};
private static final String[] values =
{"valueA", "valueB", "valueC", "valueD", "valueE"};
private static final Class<?>[] types = {String.class};
public static void main(final String[] args)
throws SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
// Reflection setting values - everything else is here solely to make this an SSCCE
final Test test = new Test();
final Class<Test> clazz = Test.class;
for(int i = 0; i < chars.length; i++) {
final String name = "setField" + chars[i];
final Method method = clazz.getDeclaredMethod(name, types);
final Object[] params = {values[i]};
method.invoke(test, params);
}
// End of reflection
System.out.println(test.getFieldA());
System.out.println(test.getFieldB());
System.out.println(test.getFieldC());
System.out.println(test.getFieldD());
System.out.println(test.getFieldE());
}
}
Upvotes: 1