2013-05-07 15 views

risposta

160

Bene, lo puoi fare anche con Jackson. (e sembra essere più comodo da quando stavi considerando l'utilizzo di Jackson).

Usa ObjectMapper s' convertValue metodo:

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

Non c'è bisogno di convertire in stringa JSON o qualcos'altro; la conversione diretta è molto più veloce.

+0

Puoi fornire il comando gradle per questa libreria? –

+2

È necessario includere questa libreria per utilizzare ObjectMapper 'compile 'com.fasterxml.jackson.core: jackson-databind: 2.7.3'' –

+1

Utilizzare convertValue è la risposta corretta, ma non creare un'istanza ObjectMapper ogni volta. È costoso da creare e sicuro per i thread, quindi creane uno e caricalo da qualche parte. – glade

2

Sì, è sicuramente possibile evitare la conversione intermedia in JSON. Utilizzando uno strumento di copia profonda come Dozer puoi convertire la mappa direttamente in un POJO. Ecco un esempio semplicistico:

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

codice di conversione del campione:

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

uscita:

MyPojo [id = 5, name = Bob, età = 23, risparmio = 2500.39]

Nota: se si modifica la mappa di origine su Map<String, Object>, è possibile copiare proprietà nidificate a profondità arbitraria (con Map<String, String> si ottiene solo un livello).

+0

grazie - molto utile. – user86834

+1

Come si può eseguire una "copia profonda" da Mappa a POJO? Supponiamo ad esempio che tu abbia una User.class che incapsula un Address.class e che la mappa abbia una chiave come "address.city", "address.zip" e che questi debbano mappare a User.Address.City e User.Address.Zip ? Non sembra interpretare automaticamente il punto nel tasto Mappa come sottolivello del grafico dell'oggetto. – szxnyc

20

Una soluzione con Gson:

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

Fantastico !!!!!!!! – TechBee

3

Ho testato sia Jackson e BeanUtils e scoperto che BeanUtils è molto più veloce.
Nella mia macchina (Windows8.1, JDK1.7) ho ottenuto questo risultato.

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

La differenza è: Jackson ha un intero quadro di conversione di tipo con esso. per esempio. la 'Mappa' contiene' map.put ("data", "2016-06-26") 'e' TestClass' ha un campo 'Dati LocalDate privati;', quindi Jackson sarebbe in grado di fare le cose, mentre BeanUtils fallire. –

Problemi correlati