2011-12-07 19 views
6

Sto espirando con serializzazione Jackson/deserializzazione. Per esempio, non ho tale classe:serializzazione lista Jackson complessa

class Base{ 
    String baseId; 
} 

e voglio serializzare objs List; Per farlo con Jackson, ho bisogno di specificare gli elementi di una lista di tipo reale, a causa della cancellazione del tipo java. Questo codice funzionerà:

List<Base> data = getData(); 
return new ObjectMapper().writerWithType(TypeFactory.collectionType(List.class, Base.class)).writeValueAsString(data); 

Ora, voglio serializzare classe più complessa:

class Result{ 
    List<Base> data; 
} 

Come devo dire a Jackson di serializzare correttamente questa classe?

+1

Nota: l'uso di TypeFactory nel codice di esempio nella domanda originale non è consigliato. Utilizzare invece mapper.getTypeFactory(). ConstructCollectionType(). –

+0

Non ho indovinato come specificare l'elenco come argomento constructCollectionType. Ecco perché ho usato collectionType lì. – tmp120210

risposta

14

Proprio

new ObjectMapper().writeValueAsString(myResult); 

Il tipo di lista non saranno persi a causa di cancellazione del tipo nello stesso modo sarebbe nel primo esempio.


Si noti che per la vaniglia la serializzazione di una lista o elenco generico, non è necessario specificare i tipi di componenti elenco, come dimostrato nel esempio nella domanda iniziale. Tutte e tre le seguenti serializzazioni di esempio rappresentano lo List<Bar> con lo stesso JSON identico.

import java.util.ArrayList; 
import java.util.List; 

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; 
import org.codehaus.jackson.annotate.JsonMethod; 
import org.codehaus.jackson.map.ObjectMapper; 
import org.codehaus.jackson.map.ObjectWriter; 

public class JacksonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    Baz baz = new Baz("BAZ", 42); 
    Zab zab = new Zab("ZAB", true); 
    List<Bar> bars = new ArrayList<Bar>(); 
    bars.add(baz); 
    bars.add(zab); 

    ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY); 

    String json1 = mapper.writeValueAsString(bars); 
    System.out.println(json1); 
    // output: 
    // [{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}] 

    Foo foo = new Foo(bars); 

    String json2 = mapper.writeValueAsString(foo); 
    System.out.println(json2); 
    // output: 
    // {"bars":[{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}]} 

    mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY); 
    ObjectWriter typedWriter = mapper.writerWithType(mapper.getTypeFactory().constructCollectionType(List.class, Bar.class)); 

    String json3 = typedWriter.writeValueAsString(bars); 
    System.out.println(json3); 
    // output: 
    // [{"name":"BAZ","size":42},{"name":"ZAB","hungry":true}] 
    } 
} 

class Foo 
{ 
    List<Bar> bars; 
    Foo(List<Bar> b) {bars = b;} 
} 

abstract class Bar 
{ 
    String name; 
    Bar(String n) {name = n;} 
} 

class Baz extends Bar 
{ 
    int size; 
    Baz(String n, int s) {super(n); size = s;} 
} 

class Zab extends Bar 
{ 
    boolean hungry; 
    Zab(String n, boolean h) {super(n); hungry = h;} 
} 

Un writer digitato è utile per la serializzazione con informazioni di tipo aggiuntive. Si noti come le uscite json1 e json3 di seguito differiscono.

import java.util.ArrayList; 
import java.util.List; 

import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; 
import org.codehaus.jackson.annotate.JsonMethod; 
import org.codehaus.jackson.map.ObjectMapper; 
import org.codehaus.jackson.map.ObjectMapper.DefaultTyping; 
import org.codehaus.jackson.map.ObjectWriter; 

public class JacksonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    Baz baz = new Baz("BAZ", 42); 
    Zab zab = new Zab("ZAB", true); 
    List<Bar> bars = new ArrayList<Bar>(); 
    bars.add(baz); 
    bars.add(zab); 

    ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY); 
    mapper.enableDefaultTypingAsProperty(DefaultTyping.OBJECT_AND_NON_CONCRETE, "type"); 

    String json1 = mapper.writeValueAsString(bars); 
    System.out.println(json1); 
    // output: 
    // [ 
    // {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42}, 
    // {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true} 
    // ] 

    Foo foo = new Foo(bars); 

    String json2 = mapper.writeValueAsString(foo); 
    System.out.println(json2); 
    // output: 
    // { 
    // "bars": 
    // [ 
    //  "java.util.ArrayList", 
    //  [ 
    //  {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42}, 
    //  {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true} 
    //  ] 
    // ] 
    // } 

    mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY); 
    mapper.enableDefaultTypingAsProperty(DefaultTyping.OBJECT_AND_NON_CONCRETE, "type"); 
    ObjectWriter typedWriter = mapper.writerWithType(mapper.getTypeFactory().constructCollectionType(List.class, Bar.class)); 

    String json3 = typedWriter.writeValueAsString(bars); 
    System.out.println(json3); 
    // output: 
    // [ 
    // "java.util.ArrayList", 
    // [ 
    //  {"type":"com.stackoverflow.q8416904.Baz","name":"BAZ","size":42}, 
    //  {"type":"com.stackoverflow.q8416904.Zab","name":"ZAB","hungry":true} 
    // ] 
    // ] 
    } 
} 
+0

Ah oh, ero così vicino alla soluzione) Qualcosa mi ha dato un NPE quando l'ho provato la prima volta, e ho pensato che non funzionasse. Ora ho provato di nuovo e tutto funziona. Grazie! – tmp120210

Problemi correlati