Rberino Mu
Rberino Mu

Reputation: 13

How to inject a map of key-value pairs into an Object with just Core Java?

How can I inject a map into an object using only Core Java?

I have a map with 4 key-value(String, Object) pairs and a class with 3 fields, I want to invoke the setter method based on the key name and set them.

{
 "variableA": "A",
 "variableB": true,
 "variableC": 1,
 "variableD": "DONT USE"
}

public Class Example {
  public void setVaraibleA(String variableA);
  public void setVaraibleB(Boolean variableB);
  public void setVaraibleC(Integer variableC);
}

Example example = new Example();
// Do something to map it
assert(example.getVariableA.equals("A"));
assert(example.getVariableB.equals(true));
assert(example.getVariableC.equals(1));

Upvotes: 1

Views: 650

Answers (2)

Jon Thoms
Jon Thoms

Reputation: 10749

Alternatively to @BeppeC's answer, if you can't easily determine the type of the object that you're injecting at runtime, and assuming that you don't have duplicate property names, I would use Class's getMethods() method and Method's getName() method.

Basically, I would write some code like the following:

Method[] exampleMethods = Example.class.getMethods();
Map<String, Method> setterMethodsByPropertyName = new HashMap<>(exampleMethods.length);
for (Method exampleMethod : exampleMethods) {
  String methodName = exampleMethod.getName();
  if (!methodName.startsWith("set")) {
    continue;
  }
  // substring starting right after "set"
  String variableName = methodName.substring(3);
  // use lowercase here because:
  // 1. JSON property starts with lower case but setter name after "set" starts with upper case
  // 2. property names should all be different so no name conflict (assumption)
  String lcVariableNmae = variableName.toLowerCase();
  setterMethodsByPropertyName.put(lcVariableName, exampleMethod);
}

// later in the code, and assuming that your JSON map is accessible via a Java Map
for (Map.Entry<String, ?> entry : jsonMap.entrySet()) {
  String propertyName = entry.getKey();
  String lcPropertyName = propertyName.toLowerCase();
  if(!setterMethodsByPropertyName.containsKey(lcPropertyName)) {
    // do something for this error condition where the property setter can't be found
  }
  Object propertyValue = entry.getValue();
  Method setter = setterMethodsByPropertyName.get(lcPropertyName);
  setter.invoke(myExampleInstance, propertyValue);
}

Upvotes: 0

Beppe C
Beppe C

Reputation: 13933

you can use Java Reflection to get a method (given its name) and invoke it with a given parameter.

Example example = new Example();
Method method = Example.class.getMethod("setVariableA", String.class);

method.invoke(example, "parameter-value1");

Upvotes: 1

Related Questions