답변:
음, 잭슨도 그렇게 할 수 있습니다. (그리고 잭슨 사용을 고려한 이후로 더 편안해 보입니다).
ObjectMapper
의 convertValue
방법을 사용하십시오 .
final ObjectMapper mapper = new ObjectMapper(); // jackson's objectmapper
final MyPojo pojo = mapper.convertValue(map, MyPojo.class);
JSON 문자열 또는 다른 것으로 변환 할 필요가 없습니다. 직접 변환은 훨씬 빠릅니다.
Map<String, Object>
인스턴스 로 딥 변환하는 방법을 알아 냈 습니까?
Gson 을 사용한 솔루션 :
Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(map);
MyPojo pojo = gson.fromJson(jsonElement, MyPojo.class);
map.toString()
올바른 문자열을 제공 한다고 생각 하십니까? 구현이 toString()
특정 형식을 보장하지는 않습니다.
예, JSON으로의 중간 변환을 피할 수 있습니다. Dozer 와 같은 심도 복사 도구를 사용 하여지도를 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>
한 수준 만 가져옴).
클래스에 제네릭 형식이 있으면와 TypeReference
함께 사용해야합니다 convertValue()
.
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>>() {});
Jackson과 BeanUtils를 모두 테스트했으며 BeanUtils가 훨씬 빠르다는 것을 알았습니다.
내 컴퓨터 (Windows8.1, JDK1.7) 에서이 결과를 얻었습니다.
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
contains map.put("data","2016-06-26")
와 TestClass
field private LocalDate data;
가 있으면 Jackson은 작업을 수행 할 수 있지만 BeanUtils는 실패합니다.
ObjectMapper
인스턴스 생성 은 시간 / 자원 소비 프로세스 라고 들었는데 매번 새로 생성하는 대신 매퍼 인스턴스 하나를 재사용하는 것이 좋습니다. 나는 테스트 lop에서 그것을 꺼내는 것이 좋을 것이라고 생각한다
지금까지 Jackson을 사용하여 제공된 답변은 훌륭하지만 여전히 다음과 같이 다른 s 를 변환 하는 데 도움 이되는 util 기능을 사용할 수 있습니다 .POJO
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;
}
Map을 POJO로 변환 예제. Map 키에 밑줄이 있고 필드 변수가 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;
}
App.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)
*/
@Hamedz 많은 데이터를 사용하는 경우, 가벼운 데이터를 변환하기 위해 Jackson을 사용하고, 아파치를 사용하십시오 ... 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'