2011-12-07 18 views
6

Estoy complicándome con la serialización/deserialización de Jackson. Por ejemplo, tengo dicha clase:serialización de la lista compleja de Jackson

class Base{ 
    String baseId; 
} 

y quiero serializar objs lista; Para hacerlo con jackson, necesito especificar los elementos de una lista tipo real, debido a la eliminación del tipo de Java. Este código funcionará:

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

Ahora, quiero serializar la clase más compleja:

class Result{ 
    List<Base> data; 
} 

Cómo debería decir a Jackson para serializar correctamente esta clase?

+1

Nota: No se recomienda el uso de TypeFactory en el código de ejemplo de la pregunta original. En su lugar, use mapper.getTypeFactory(). ConstructCollectionType(). –

+0

No adiviné cómo especificar la lista como argumento constructCollectionType. Es por eso que utilicé collectionType allí. – tmp120210

Respuesta

14

Sólo

new ObjectMapper().writeValueAsString(myResult); 

El tipo de la lista no se perderán debido al tipo de borrado de la misma manera que sería en el primer ejemplo.


Tenga en cuenta que para la serialización de vainilla de una lista o una lista genérica, no es necesario especificar los tipos de componentes lista, como se demuestra en el ejemplo en la pregunta original. Las tres siguientes serializaciones de ejemplo representan el List<Bar> con el mismo JSON exacto.

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 escritor mecanografiado es útil al serializar con información de tipo adicional. Observe cómo las salidas json1 y json3 a continuación difieren.

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, estaba tan cerca de la solución) Algo me dio una NPE cuando lo probé por primera vez, y pensé que no funcionaría. Ahora lo intenté de nuevo y todo funciona. ¡Gracias! – tmp120210

Cuestiones relacionadas