Convert a Map<String, String> to a POJO

JsonDictionaryJacksonPojo

Json Problem Overview


I've been looking at Jackson, but is seems I would have to convert the Map to JSON, and then the resulting JSON to the POJO.

Is there a way to convert a Map directly to a POJO?

Json Solutions


Solution 1 - Json

Well, you can achieve that with Jackson, too. (and it seems to be more comfortable since you were considering using jackson).

Use ObjectMapper's convertValue method:

final ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper
final MyPojo pojo = mapper.convertValue(map, MyPojo.class);

No need to convert into JSON string or something else; direct conversion does much faster.

Solution 2 - Json

A solution with Gson:

Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(map);
MyPojo pojo = gson.fromJson(jsonElement, MyPojo.class);

Solution 3 - Json

if you have generic types in your class you should use TypeReference with convertValue().

final ObjectMapper mapper = new ObjectMapper();
final MyPojo<MyGenericType> pojo = mapper.convertValue(map, new TypeReference<MyPojo<MyGenericType>>() {});

Also you can use that to convert a pojo to java.util.Map back.

final ObjectMapper mapper = new ObjectMapper();
final Map<String, Object> map = mapper.convertValue(pojo, new TypeReference<Map<String, Object>>() {});

Solution 4 - Json

 ObjectMapper objectMapper = new ObjectMapper();
 //if all properties are not in class use this
 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 final MyPojo pojo =     objectMapper.convertValue(map, MyPojo.class);

same as first answer but i got an error using that because i dont want all property of the map converted to the calss. and i fount objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); this as the solution

Solution 5 - Json

Yes, its definitely possible to avoid the intermediate conversion to JSON. Using a deep-copy tool like Dozer you can convert the map directly to a POJO. Here is a simplistic example:

Example POJO:

public class MyPojo implements Serializable {
    private static final long serialVersionUID = 1L;

    private String id;
    private String name;
    private Integer age;
    private Double savings;

    public MyPojo() {
        super();
    }

    // Getters/setters

    @Override
    public String toString() {
        return String.format(
                "MyPojo[id = %s, name = %s, age = %s, savings = %s]", getId(),
                getName(), getAge(), getSavings());
    }
}

Sample conversion code:

public class CopyTest {
    @Test
    public void testCopyMapToPOJO() throws Exception {
        final Map<String, String> map = new HashMap<String, String>(4);
        map.put("id", "5");
        map.put("name", "Bob");
        map.put("age", "23");
        map.put("savings", "2500.39");
        map.put("extra", "foo");

        final DozerBeanMapper mapper = new DozerBeanMapper();
        final MyPojo pojo = mapper.map(map, MyPojo.class);
        System.out.println(pojo);
    }
}

Output:

>MyPojo[id = 5, name = Bob, age = 23, savings = 2500.39]

Note: If you change your source map to a Map<String, Object> then you can copy over arbitrarily deep nested properties (with Map<String, String> you only get one level).

Solution 6 - Json

I have tested both Jackson and BeanUtils and found out that BeanUtils is much faster.
In my machine(Windows8.1 , JDK1.7) I got this result.

BeanUtils t2-t1 = 286
Jackson t2-t1 = 2203


public class MainMapToPOJO {

public static final int LOOP_MAX_COUNT = 1000;

public static void main(String[] args) {
    Map<String, Object> map = new HashMap<>();
    map.put("success", true);
    map.put("data", "testString");

    runBeanUtilsPopulate(map);

    runJacksonMapper(map);
}

private static void runBeanUtilsPopulate(Map<String, Object> map) {
    long t1 = System.currentTimeMillis();
    for (int i = 0; i < LOOP_MAX_COUNT; i++) {
        try {
            TestClass bean = new TestClass();
            BeanUtils.populate(bean, map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
    long t2 = System.currentTimeMillis();
    System.out.println("BeanUtils t2-t1 = " + String.valueOf(t2 - t1));
}

private static void runJacksonMapper(Map<String, Object> map) {
    long t1 = System.currentTimeMillis();
    for (int i = 0; i < LOOP_MAX_COUNT; i++) {
        ObjectMapper mapper = new ObjectMapper();
        TestClass testClass = mapper.convertValue(map, TestClass.class);
    }
    long t2 = System.currentTimeMillis();
    System.out.println("Jackson t2-t1 = " + String.valueOf(t2 - t1));
}}

Solution 7 - Json

The answers provided so far using Jackson are so good, but still you could have a util function to help you convert different POJOs as follows:

    public static <T> T convert(Map<String, Object> aMap, Class<T> t) {
        try {
            return objectMapper
                    .convertValue(aMap, objectMapper.getTypeFactory().constructType(t));
        } catch (Exception e) {
            log.error("converting failed! aMap: {}, class: {}", getJsonString(aMap), t.getClass().getSimpleName(), e);
        }
        return null;
    }

Solution 8 - Json

> convert Map to POJO example.Notice the Map key contains underline and field variable is hump.

User.class POJO

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

@Data
public class User {
    @JsonProperty("user_name")
    private String userName;
    @JsonProperty("pass_word")
    private String passWord;
}

The App.class test the example

import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;

public class App {
    public static void main(String[] args) {
        Map<String, String> info = new HashMap<>();
        info.put("user_name", "Q10Viking");
        info.put("pass_word", "123456");

        ObjectMapper mapper = new ObjectMapper();
        User user = mapper.convertValue(info, User.class);

        System.out.println("-------------------------------");
        System.out.println(user);
    }
}
/**output
-------------------------------
User(userName=Q10Viking, passWord=123456)
 */

Solution 9 - Json

@Hamedz if use many data, use Jackson to convert light data, use apache... TestCase:



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

import org.apache.commons.beanutils.BeanUtils;

import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

public class TestPerf {

	public static final int LOOP_MAX_COUNT = 1000;

	public static void main(String[] args) {
		Map<String, Object> map = new HashMap<>();
		map.put("success", true);
		map.put("number", 1000);
		map.put("longer", 1000L);
		map.put("doubler", 1000D);
		map.put("data1", "testString");
		map.put("data2", "testString");
		map.put("data3", "testString");
		map.put("data4", "testString");
		map.put("data5", "testString");
		map.put("data6", "testString");
		map.put("data7", "testString");
		map.put("data8", "testString");
		map.put("data9", "testString");
		map.put("data10", "testString");

		runBeanUtilsPopulate(map);

		runJacksonMapper(map);
	}

	private static void runBeanUtilsPopulate(Map<String, Object> map) {
		long t1 = System.currentTimeMillis();
		for (int i = 0; i < LOOP_MAX_COUNT; i++) {
			try {
				TestClass bean = new TestClass();
				BeanUtils.populate(bean, map);
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
		}
		long t2 = System.currentTimeMillis();
		System.out.println("BeanUtils t2-t1 = " + String.valueOf(t2 - t1));
	}

	private static void runJacksonMapper(Map<String, Object> map) {
		long t1 = System.currentTimeMillis();
		for (int i = 0; i < LOOP_MAX_COUNT; i++) {
			ObjectMapper mapper = new ObjectMapper();
			TestClass testClass = mapper.convertValue(map, TestClass.class);
		}
		long t2 = System.currentTimeMillis();
		System.out.println("Jackson t2-t1 = " + String.valueOf(t2 - t1));
	}

	@Data
	@AllArgsConstructor
	@NoArgsConstructor
	public static class TestClass {
		private Boolean success;
		private Integer number;
		private Long longer;
		private Double doubler;
		private String data1;
		private String data2;
		private String data3;
		private String data4;
		private String data5;
		private String data6;
		private String data7;
		private String data8;
		private String data9;
		private String data10;

	}
}


Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser86834View Question on Stackoverflow
Solution 1 - JsonJongwook ChoiView Answer on Stackoverflow
Solution 2 - JsonAlikElzin-kilakaView Answer on Stackoverflow
Solution 3 - JsonbhdrkView Answer on Stackoverflow
Solution 4 - JsonShafeeq MohammedView Answer on Stackoverflow
Solution 5 - JsonPerceptionView Answer on Stackoverflow
Solution 6 - JsonHamedzView Answer on Stackoverflow
Solution 7 - JsonHearenView Answer on Stackoverflow
Solution 8 - JsonQ10VikingView Answer on Stackoverflow
Solution 9 - JsonFernando RozaView Answer on Stackoverflow