Home > Enterprise >  Jackson deserialize dynamically by class fully Qualified Name
Jackson deserialize dynamically by class fully Qualified Name

Time:01-31

I am working on the framework which has these requirements

Developers develop their classes ( Beans ) like below

class BeanA{
  
    int id;
    String appName;

   public void save() 
}

class BeanB{
  
    int id;
    String userName;

   public void save() 
}

There is orchestratoon.csv is also defined like this where developer makes the entry of their class

org.example.BeanA, http://fetch/bean/a/from/this/url
org.example.BeanB, http://fetch/bean/b/from/this/url
org.example.BeanC, http://fetch/bean/c/from/this/url

After this, I have to write a platform service, which will fetch the Beans data from the url given in the orchestration.csv file and render then in the class provided by their fully qualified name

My problem is, how can I deserialize the json fetched into the class given by its name and call a save method of that bean.

Below is the psuedo code.

ObjectMapper objectMapper = new ObjectMapper();

for className, URL in CSV
  
   String json = getObject(url)

   // Here is the problem, how do I deserialize it using ObjectMapper 
   
     objectMapper.readValue(json, Class.forName(className));   ---> It does not work , compile time error because of Class.forName and how do I call a save on it

Any help would

CodePudding user response:

Extract the save() method in an interface or abstract class, depending on your exact scenario. In most cases interface is better choice:

public interface MyInterface {

  void save();
}

Have BeanA, BeanB, etc. implement it. Cast the deserialization result to MyInterface and invoke save().

Object object;
try {
  object = objectMapper.readValue(json, Class.forName("bean.class.full.name"));
} catch (JsonProcessingException exc) {
  throw new RuntimeException("invalid json", exc);
}
if (object instanceof MyInterface myInterface) {
  myInterface.save();
} else {
  throw new RuntimeException("appropriate message here");
}

CodePudding user response:

Assuming that you managed to read the JSON string that represents particular class from your URL and you know the class name. So you can use ObjectMapper class and its method <T> T readValue(String content, Class<T> valueType). Place your json string as a content and as for class use
public static Class<?> forName(String className) throws ClassNotFoundException. See ObjectMapper javadoc here. Also, if you want it even simpler I wrote my own JsonUtil where you don't even have to instantiate ObjectMapper. Your code would look like this:

 try {
    BeanB beanB = JsonUtils.readObjectFromJsonString(jsonStr, Class.forName(classNameStr));
} catch (IOException ioe) {
    ...
}

In this example class JsonUtils comes with Open Source MgntUtils library written and maintained by me. See the Javadoc for JsonUtils class. The MgntUtils library can be obtained from Maven Central as Maven artifact or from Github along with Source code and Javadoc

  • Related