BeanUtils converting java.util.Map to nested bean

22,191

Solution 1

You should use Spring's BeanWrapper class. It supports nested properties, and optionally create inner beans for you:

BeanOne one = new BeanOne();
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(one);
wrapper.setAutoGrowNestedPaths(true);

Map<String, Object> map = new HashMap<>();
map.put("fieldOne", "fieldOneValue");
map.put("fieldTwo.fieldOne", "fieldOneValue");

wrapper.setPropertyValues(map);

assertEquals("fieldOneValue", one.getFieldOne());
BeanTwo two = one.getFieldTwo();
assertNotNull(two);
assertEquals("fieldOneValue", two.getFieldOne();

The killer feature of auto-creating inner beans is achieved thanks to wrapper.setAutoGrowNestedPaths(true). The default value is false, which means you will get a NullValueInNestedPathException if an element in the property path is null.

Solution 2

Here we go you can do like this....

BeanOne.java

import java.util.Map;

public class BeanOne {
    private String fieldOne;
    private Map<String,BeanTwo> fieldTwo;
    public Map<String, BeanTwo> getFieldTwo() {
        return fieldTwo;
    }

    public void setFieldTwo(Map<String, BeanTwo> fieldTwo) {
        this.fieldTwo = fieldTwo;
    }

    public String getFieldOne() {
        return this.fieldOne;
    }

    public void setFieldOne(String fieldOne) {
        this.fieldOne = fieldOne;
    }
}

BeanTwo.java

public class BeanTwo {
    private String fieldOne;

    public String getFieldOne() {
        return this.fieldOne;
    }

    public void setFieldOne(String fieldOne) {
        this.fieldOne = fieldOne;
    }
}

Tester.java

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

public class Tester {
    public static void main(String[] args) throws IllegalAccessException,
            InvocationTargetException {
        Map beanTwoMap = new HashMap();
        beanTwoMap.put("fieldOne", "fieldOne2222Value");
        Map beanOneMap = new HashMap();
        beanOneMap.put("fieldOne", "fieldOneValue");
        beanOneMap.put("fieldTwo", beanTwoMap);
        BeanOne beanOne = new BeanOne();
        BeanUtils.populate(beanOne, beanOneMap);
        System.out.println(beanOne.getFieldOne());
        System.out.println(beanOne.getFieldTwo().get("fieldOne"));
    }

}

output will be:-

fieldOneValue
fieldOne2222Value
Share:
22,191
Skynet
Author by

Skynet

Software Engineer

Updated on July 09, 2022

Comments

  • Skynet
    Skynet almost 2 years

    I have a Java bean which has a field which in turn is another bean

    public class BeanOne {
       private String fieldOne;
       private BeanTwo fieldTwo;
    
       public String getFieldOne() {return this.fieldOne;}  
       public void setFieldOne(String fieldOne){this.fieldOne = fieldOne}
    
       public BeanTwo getFieldTwo() {return this.fieldTwo;}  
       public void setFieldTwo(BeanTwo fieldTwo){this.fieldTwo = fieldTwo}
    }
    
    public class BeanTwo {
       private String fieldOne;
    
       public String getFieldOne() {return this.fieldOne;}  
       public void setFieldOne(String fieldOne){this.fieldOne = fieldOne}
    }
    

    I am trying to pass a map to BeanUtils to try and convert the following map into BeanOne

    Map beanOneMap = new HashMap<String, Object>();
    beanOneMap.put("fieldOne", "fieldOneValue");
    Map beanTwoMap = new HashMap<String, Object>();
    beanTwoMap.put("fieldOne", "fieldOneValue");
    beanOneMap.put("fieldTwo", beanTwoMap);
    
    BeanOne beanOne = new BeanOne();
    BeanUtils.populate(beanOne, beanOneMap);
    

    But it throws an error saying - Cannot invoke BeanOne.setFieldTwo on bean class 'class Bean' - argument type mismatch - had objects of type "java.util.HashMap" but expected signature "BeanTwo"

    How can I use BeanUtils to correctly populate the inner bean ?

  • kkkkkk
    kkkkkk over 6 years
    I use spring mvc in my project, and this solution is the best for me. Think about spring mvc auto bind JSON to your bean, spring works very well. So, this convert map to bean solution is really really good.