关于json:将Map 转换为POJO

Convert a Map to a POJO

我一直在查看Jackson,但似乎我必须将Map转换为JSON,然后将所得的JSON转换为POJO。

有没有一种方法可以将Map直接转换为POJO?


好吧,您也可以使用Jackson来实现。 (由于您正在考虑使用杰克逊,因此似乎更舒适)。

使用ObjectMapperconvertValue方法:

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

无需转换为JSON字符串或其他内容;直接转换的速度要快得多。


Gson的解决方案:

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


是的,绝对有可能避免中间转换为JSON。使用类似Dozer的深度复制工具,您可以将地图直接转换为POJO。这是一个简单的例子:

示例POJO:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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());
    }
}

转换代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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, name = Bob, age = 23, savings = 2500.39]

注意:如果将源映射更改为Map,则可以在任意深度嵌套的属性上进行复制(使用Map只能获得一个级别)。


如果您的班级中有通用类型,则应将TypeReferenceconvertValue()一起使用。

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

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

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

我测试了Jackson和BeanUtils,发现BeanUtils更快。
在我的机器上(Windows8.1,JDK1.7)我得到了这个结果。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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));
}}


哈密??兹
如果使用许多数据,请使用Jackson进行转换
轻量数据,使用Apache ...
测试用例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<wyn>
</p>

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;

    }
}


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

用户类POJO

1
2
3
4
5
6
7
8
9
10
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;
}

App.class测试示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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)
 */