user1068636
user1068636

Reputation: 1939

How do I leverage a json mapping file to convert from one pojo to another pojo?

I have two POJOs (Person.java and User.java) that contain similar information. See below:

public class Person {

    private String first_name;
    private String last_name;
    private Integer age;
    private Integer weight;
    private Integer height;

    public String getFirst_name() {
        return first_name;
    }

    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }

    public String getLast_name() {
        return last_name;
    }

    public void setLast_name(String last_name) {
        this.last_name = last_name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

}



public class User {
    private String name_first;
    private String name_last;
    private Integer my_age;
    private Integer my_weight;
    private String social_security;

    public String getName_first() {
        return name_first;
    }

    public void setName_first(String name_first) {
        this.name_first = name_first;
    }

    public String getName_last() {
        return name_last;
    }

    public void setName_last(String name_last) {
        this.name_last = name_last;
    }

    public Integer getMy_age() {
        return my_age;
    }

    public void setMy_age(Integer my_age) {
        this.my_age = my_age;
    }

    public Integer getMy_weight() {
        return my_weight;
    }

    public void setMy_weight(Integer my_weight) {
        this.my_weight = my_weight;
    }

    public String getSocial_security() {
        return social_security;
    }

    public void setSocial_security(String social_security) {
        this.social_security = social_security;
    }
    
    
}

I have defined a mapping.json file as shown below using GSON.

{
  "columnMap": [
    {
      "userColumn": "name_first",
      "personColumn": "first_name"
    },
    {
      "userColumn": "last_first",
      "personColumn": "first_last"
    },
    {
      "userColumn": "my_age",
      "personColumn": "age"
    },
    {
      "userColumn": "my_weight",
      "personColumn": "weight"
    }
  ]
}


public class Mapping {
    
    private ArrayList<Pair> columnMap;
    
    public Mapping(){
        columnMap = new ArrayList<>();
    }

    public ArrayList<Pair> getColumnMap() {
        return columnMap;
    }

    public void setColumnMap(ArrayList<Pair> columnMap) {
        this.columnMap = columnMap;
    }   
}

I am writing a utility class helper function that converts between a Person and User object the mapped pairs.

public class Pair {
    private String userColumn;
    private String personColumn;

    public String getUserColumn() {
        return userColumn;
    }

    public void setUserColumn(String userColumn) {
        this.userColumn = userColumn;
    }

    public String getPersonColumn() {
        return personColumn;
    }

    public void setPersonColumn(String personColumn) {
        this.personColumn = personColumn;
    }
    
    public static void main(String args[]){
        
        
    }
    
}

My question is below: As you can see the returnVal object is being set by me (the programmer) to convert from a User POJO to a Person POJO. How do I leverage the pre-defined mapping.json to do this? The reason I am asking is in the future, the mapping.json file may change (maybe the weight mapping no longer exists). So I am trying to avoid re-programming this Utility.userToPerson() function. How can I achieve this? I am thinking Java reflection is the way to go, but I would like to hear back from the Java community.

public class Utility {
    public static Person userToPerson(User u){
        Person returnVal = new Person();
        
        returnVal.setAge(u.getMy_age()); // <-- Question How do I leverage mapping.json here?  
        returnVal.setFirst_name(u.getName_first());
        returnVal.setLast_name(u.getName_last());
        returnVal.setWeight(u.getMy_weight());
        
        return returnVal;
    }
}

Upvotes: 0

Views: 30

Answers (1)

Atul Dwivedi
Atul Dwivedi

Reputation: 1462

You can introspect the beans (i.e. User and Person) for the field names and call corresponding getter from User to fetch the value. Later call corresponding setter in Person.

Here I have taken userToPersonFieldsMap for mapping the field, you can load mapping from JSON file and construct the map accordingly.

Important code section is the for loop, where it dynamically calls getter and setter and does the job.

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

public class UserToPersonMapper {
    public static void main(String[] args) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
        Map<String, String> userToPersonFieldsMap = new HashMap<>();
        userToPersonFieldsMap.put("name_first", "first_name");
        userToPersonFieldsMap.put("last_first", "first_last");
        userToPersonFieldsMap.put("age", "personAge");

        //existing user
        User user = new User("Tony", "Stark", 20);

        //new person - to be initialised with values from user
        Person person = new Person();

        for (Map.Entry<String, String> entry : userToPersonFieldsMap.entrySet()) {
            Object userVal = new PropertyDescriptor(entry.getKey(), User.class).getReadMethod().invoke(user);
            new PropertyDescriptor(entry.getValue(), Person.class).getWriteMethod().invoke(person, userVal);
        }

        System.out.println(user);
        System.out.println(person);
    }
}

class User {
    private String name_first;
    private String last_first;
    private int age;

    public User(String name_first, String last_first, int age) {
        this.name_first = name_first;
        this.last_first = last_first;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName_first() {
        return name_first;
    }

    public String getLast_first() {
        return last_first;
    }

    public void setName_first(String name_first) {
        this.name_first = name_first;
    }

    public void setLast_first(String last_first) {
        this.last_first = last_first;
    }

    @Override
    public String toString() {
        return "User{" +
                "name_first='" + name_first + '\'' +
                ", last_first='" + last_first + '\'' +
                ", age=" + age +
                '}';
    }
}

class Person {
    private String first_name;
    private String first_last;
    private int personAge;

    public void setFirst_name(String first_name) {
        this.first_name = first_name;
    }

    public void setFirst_last(String first_last) {
        this.first_last = first_last;
    }

    public String getFirst_name() {
        return first_name;
    }

    public String getFirst_last() {
        return first_last;
    }

    public int getPersonAge() {
        return personAge;
    }

    public void setPersonAge(int personAge) {
        this.personAge = personAge;
    }

    @Override
    public String toString() {
        return "Person{" +
                "first_name='" + first_name + '\'' +
                ", first_last='" + first_last + '\'' +
                ", personAge=" + personAge +
                '}';
    }
}

You can tweak and try it out this example to make it more align with your requirement.

Note:

This solution uses reflection.

Upvotes: 1

Related Questions