Copy properties from one bean to another (not the same class) recursively (including nested beans)

Sergey Pauk picture Sergey Pauk · Mar 27, 2015 · Viewed 19.9k times · Source

Which approach requires the least amount of own written code to achieve a deep copy of one bean to another? The goal is to do it in an automatic way when source and target properties are matched by name.

source main bean:

public class SourceBean {
    private String beanField;
    private SourceNestedBean nestedBean;

    // getters and setters
}

source nested bean:

public class SourceNestedBean {
    private String nestedBeanField;

    // getters and setters
}

target main bean:

public class TargetBean {
    private String beanField;
    private TargetNestedBean nestedBean;

    // getters and setters        
}

target nested bean:

public class TargetNestedBean {
    private String nestedBeanField;

    // getters and setters
}


Using e.g. Spring BeanUtils.copyProperites() I could create a shallow copy of a SourceBean to TargetBean with one line of code but it will not copy nested beans. Is there any mature utility (not necessarily Spring Framework) that would allow to do the deep copy while writing as least own code as possible (pretty much same as BeanUtils.copyProperties())?

Answer

fps picture fps · Mar 28, 2015

One way to do it is with Jackson ObjectMapper, via the convertValue() method:

ObjectMapper mapper = new ObjectMapper();
SourceBean source = ...;
TargetBean target = mapper.convertValue(source, TargetBean.class);

Note that convertValue() is overloaded to also work with generic types. Also beware that convertValue() will in some circumstances return the value you provided, such as if SourceBean is assignable to TargetBean.

As Jackson is a JSON serialization/deserialization library, what convertValue() does is serialize source to JSON in memory, and then deserialize this JSON into an instance of TargetBean. So high performance is not to be expected. However, conversion is performed with one single line of code.

If you need performance, the best is to do the mapping manually. Nothing will be better than that.

If you need simplicity, use Jackson as explained above.

A good trade-off is Orika, a high performance mapper with almost no configuration that doesn't use reflection.