2013-05-07 13 views

Odpowiedz

160

Cóż, możesz to osiągnąć także z Jacksonem. (i wydaje się być wygodniejszym, ponieważ rozważałeś użycie jacksona).

Zastosowanie ObjectMapper „s convertValue metoda:

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

Nie ma potrzeby, aby przekształcić JSON ciąg lub coś innego; bezpośrednia konwersja działa znacznie szybciej.

+0

Czy możesz podać polecenie gradle dla tej biblioteki? –

+2

Musisz dołączyć tę bibliotekę, aby użyć ObjectMapper 'compile 'com.fasterxml.jackson.core: jackson-databind: 2.7.3'' –

+1

Używanie convertValue jest właściwą odpowiedzią, ale nie twórz instancji ObjectMapper za każdym razem. Tworzenie i bezpieczne tworzenie wątków jest kosztowne, więc utwórz je i przechowuj gdzieś w pamięci podręcznej. – glade

2

Tak, zdecydowanie można uniknąć pośredniej konwersji na JSON. Za pomocą narzędzia do kopiowania głębokiego, takiego jak Dozer, możesz zamienić mapę bezpośrednio na POJO. Tutaj jest uproszczony przykład:

Przykład 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()); 
    } 
} 

kod konwersji próbki:

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

wyjściowa:

MyPojo [id = 5, nazwa = Bob wiek = 23, oszczędności = 2500.39]

Uwaga: Jeśli zmienisz mapę źródłową na Map<String, Object>, możesz kopiować za pomocą dowolnie zagnieżdżonych właściwości (z Map<String, String> dostajesz tylko jeden poziom).

+0

dzięki - bardzo pomocne. – user86834

+1

Jak możesz zrobić "głęboką kopię" z mapy do POJO? Powiedzmy na przykład, że masz klasę User.class, która zawiera klasę Address.class, a mapa ma klucz taki jak "address.city", "address.zip", a te muszą być odwzorowane na User.Address.City i User.Address.Zip ? Nie wydaje się, aby automatycznie interpretować kropkę w klawiszu Mapa jako pod-poziom do wykresu obiektu. – szxnyc

20

Rozwiązanie z Gson:

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

Awesome !!!!!!!! – TechBee

3

Ja testowałem zarówno Jacksona i BeanUtils i okazało się, że BeanUtils jest znacznie szybsze.
W moim komputerze (Windows 8.1, JDK1.7) otrzymałem ten wynik.

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

Różnica polega na tym, że Jackson ma z nim strukturę konwersji całego typu. na przykład "Mapa" zawiera 'map.put (" dane "," 2016-06-26 ")' a 'TestClass' ma pole' prywatne dane LocalDate; ', a następnie Jackson będzie w stanie załatwić sprawy, podczas gdy BeanUtils będzie zawieść. –

Powiązane problemy