转换一个Map<String, String>到POJO

我一直在看杰克逊,但似乎我必须将地图转换为JSON,然后将结果JSON转换为POJO。

是否有方法将Map直接转换为POJO?

307723 次浏览

是的,它绝对可以避免到JSON的中间转换。使用像推土机这样的深度复制工具,你可以直接将映射转换为POJO。下面是一个简单的例子:

示例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());
}
}

转换代码示例:

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);
}
}

输出:

MyPojo[id = 5,名字= Bob,年龄= 23,存款= 2500.39]

注意:如果你将源映射更改为Map<String, Object>,那么你可以复制任意深度的嵌套属性(使用Map<String, String>你只能得到一层)。

杰克逊也能做到这一点。(而且自从你考虑使用jackson后,它似乎更舒服)。

使用ObjectMapperconvertValue方法:

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

不需要转换成JSON字符串或其他东西;直接转换要快得多。

使用Gson的解决方案:

Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(map);
MyPojo pojo = gson.fromJson(jsonElement, MyPojo.class);
我已经测试了Jackson和BeanUtils,发现BeanUtils要快得多 在我的机器(Windows8.1, JDK1.7),我得到了这个结果
BeanUtils t2-t1 = 286
Jackson t2-t1 = 2203

< br >

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));
}}

如果你的类中有泛型类型,你应该使用TypeReferenceconvertValue()

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

你也可以使用它将pojo转换回java.util.Map

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

将Map转换为POJO的例子。注意Map键包含下划线,字段变量是驼峰。

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;
}

class测试这个例子

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)
*/
< p > @Hamedz 如果使用较多的数据,则使用Jackson进行转换 光数据,使用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; } }

到目前为止使用Jackson提供的答案都很好,但是你仍然可以有一个跑龙套函数来帮助你转换不同的__abc0,如下所示:

    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;
}
 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);

与第一个答案相同,但我得到了一个错误使用,因为我不希望所有属性的地图转换为类。和我的 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);这作为解决方案