How about Mapstruct ?
Step 1: Add Dependencies to pom.xml
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
</dependencies>
Step 2: Create the Mapper Interface
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
@Mapper
public interface EmployeeMapper {
EmployeeMapper INSTANCE = Mappers.getMapper(EmployeeMapper.class);
@Mappings({
@Mapping(source = "Address.addr1", target = "ad1"),
@Mapping(source = "Address.addr2", target = "ad2"),
@Mapping(source = "Info.ageinnumber", target = "EmpInf.ageinnumber"),
@Mapping(source = "Info.birthdate", target = "EmpInf.birthdate"),
@Mapping(source = "Info.DOB", target = "EmpInf.DOB"),
@Mapping(source = "Training.tr1", target = "t1"),
@Mapping(source = "Training.AppDTO.appName", target = "appName")
})
Employee toEmployee(EmployeeDTO source);
}
Step 3: Use the Mapper
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws Exception {
String sourceJson = "{\"Employee\":{\"Address\":{\"addr1\":\"123 Main St\",\"addr2\":\"Apt 4B\",\"addr3\":\"City\"},\"Info\":{\"Age\":30,\"Birth\":\"John Doe\",\"DOB\":\"1994-05-15\",\"Gender\":\"Male\"},\"Training\":{\"tr1\":\"Training 1\",\"tr2\":\"Training 2\",\"AppDTO\":{\"appName\":\"App Name\",\"appId\":\"12345\",\"appPrice\":9.99}}}}";
ObjectMapper mapper = new ObjectMapper();
EmployeeDTO source = mapper.readValue(sourceJson, EmployeeDTO.class);
Employee target = EmployeeMapper.INSTANCE.toEmployee(source);
System.out.println(target);
}
}
Step4: Output
Employee{ad1='123 Main St', ad2='Apt 4B', EmpInf=EmployeeInformation{ageinnumber=30, birthdate='John Doe', DOB='1994-05-15'}, t1='Training 1', appName='App Name'}
Add multiple methods:
=========================
import org.mapstruct.Mapper;
@Mapper
public interface EmployeeMapper {
EmployeeDto toEmployeeDto(Employee source);
Employee toEmployee(EmployeeDto source);
}
Mapping from Employee to EmployeeDTO:
@Mappings({
@Mapping(source = "ad1", target = "Address.addr1"),
@Mapping(source = "ad2", target = "Address.addr2"),
@Mapping(source = "EmpInf.ageinnumber", target = "Info.Age"),
@Mapping(source = "EmpInf.birthdate", target = "Info.Birth"),
@Mapping(source = "EmpInf.DOB", target = "Info.DOB"),
@Mapping(source = "t1", target = "Training.tr1"),
@Mapping(source = "appName", target = "Training.AppDTO.appName")
})
EmployeeDTO toEmployeeDTO(Employee source);
Mapping from EmployeeDTO to Employee:
@Mappings({
@Mapping(source = "Address.addr1", target = "ad1"),
@Mapping(source = "Address.addr2", target = "ad2"),
@Mapping(source = "Info.Age", target = "EmpInf.ageinnumber"),
@Mapping(source = "Info.Birth", target = "EmpInf.birthdate"),
@Mapping(source = "Info.DOB", target = "EmpInf.DOB"),
@Mapping(source = "Training.tr1", target = "t1"),
@Mapping(source = "Training.AppDTO.appName", target = "appName")
})
Employee toEmployee(EmployeeDTO source);
@Mapper
public interface EmployeeMapper {
EmployeeMapper INSTANCE = Mappers.getMapper(EmployeeMapper.class);
@Mappings({
@Mapping(source = "Address.addr1", target = "ad1"),
@Mapping(source = "Address.addr2", target = "ad2"),
@Mapping(source = "Info.ageinnumber", target = "EmpInf.ageinnumber"),
@Mapping(source = "Info.birthdate", target = "EmpInf.birthdate"),
@Mapping(source = "Info.DOB", target = "EmpInf.DOB"),
@Mapping(source = "Training.tr1", target = "t1"),
@Mapping(source = "Training.AppDTO.appName", target = "appName")
})
Employee toEmployee(EmployeeDTO source);
@InheritInverseConfiguration
EmployeeDTO toEmployeeDto(Employee target);
}