Tôi đã nhìn vào Jackson, nhưng dường như tôi sẽ phải chuyển đổi Bản đồ thành JSON, và sau đó JSON kết quả thành POJO.
Có cách nào để chuyển đổi Bản đồ trực tiếp thành POJO không?
Tôi đã nhìn vào Jackson, nhưng dường như tôi sẽ phải chuyển đổi Bản đồ thành JSON, và sau đó JSON kết quả thành POJO.
Có cách nào để chuyển đổi Bản đồ trực tiếp thành POJO không?
Câu trả lời:
Chà, bạn cũng có thể đạt được điều đó với Jackson. (và có vẻ thoải mái hơn vì bạn đang cân nhắc sử dụng jackson).
Sử dụng ObjectMapper
's convertValue
phương pháp:
final ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper
final MyPojo pojo = mapper.convertValue(map, MyPojo.class);
Không cần phải chuyển đổi thành chuỗi JSON hoặc cái gì khác; chuyển đổi trực tiếp làm nhanh hơn nhiều.
Map<String, Object>
thể hiện chưa?
Một giải pháp với Gson :
Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(map);
MyPojo pojo = gson.fromJson(jsonElement, MyPojo.class);
map.toString()
sẽ cung cấp đúng chuỗi? Việc thực hiện toString()
không đảm bảo một định dạng cụ thể.
Có, chắc chắn có thể tránh được việc chuyển đổi trung gian sang JSON. Sử dụng một công cụ sao chép sâu như Dozer, bạn có thể chuyển đổi bản đồ trực tiếp thành POJO. Đây là một ví dụ đơn giản:
Ví dụ 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());
}
}
Mã chuyển đổi mẫu:
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);
}
}
Đầu ra:
MyPojo [id = 5, name = Bob, tuổi = 23, tiết kiệm = 2500,39]
Lưu ý: Nếu bạn thay đổi bản đồ nguồn của mình thành a Map<String, Object>
thì bạn có thể sao chép các thuộc tính lồng nhau sâu tùy ý (với Map<String, String>
bạn chỉ nhận được một cấp).
nếu bạn có loại chung trong lớp, bạn nên sử dụng TypeReference
với convertValue()
.
final ObjectMapper mapper = new ObjectMapper();
final MyPojo<MyGenericType> pojo = mapper.convertValue(map, new TypeReference<MyPojo<MyGenericType>>() {});
Ngoài ra, bạn có thể sử dụng điều đó để chuyển đổi một pojo java.util.Map
trở lại.
final ObjectMapper mapper = new ObjectMapper();
final Map<String, Object> map = mapper.convertValue(pojo, new TypeReference<Map<String, Object>>() {});
Tôi đã thử nghiệm cả Jackson và BeanUtils và phát hiện ra rằng BeanUtils nhanh hơn nhiều.
Trong máy của tôi (Windows8.1, JDK1.7) tôi đã nhận được kết quả này.
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));
}}
Map
chứa map.put("data","2016-06-26")
và TestClass
có một trường private LocalDate data;
, sau đó Jackson sẽ có thể hoàn thành công việc, trong khi BeanUtils sẽ thất bại.
ObjectMapper
cá thể là một quá trình tiêu tốn thời gian / tài nguyên và nên sử dụng lại một cá thể ánh xạ thay vì tạo lại nó mỗi lần. Tôi nghĩ sẽ tốt hơn nếu lấy nó ra khỏi bản thử nghiệm
Những câu trả lời cung cấp cho đến nay sử dụng Jackson rất tốt, nhưng bạn vẫn có thể có một util chức năng để giúp bạn chuyển đổi khác nhau POJO
s như sau:
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;
}
chuyển đổi Map thành ví dụ POJO. Chú ý khóa Map chứa gạch chân và biến trường là bướu.
Người dùng. Lớp 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;
}
App. Class kiểm tra ví dụ
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)
*/
@Hamedz nếu sử dụng nhiều dữ liệu, sử dụng Jackson để chuyển đổi dữ liệu ánh sáng, sử dụng 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;
}
}
compile 'com.fasterxml.jackson.core:jackson-databind:2.7.3'