I'm experementing with Jackson serialization/deserialization. For instance, I have such class:
class Base{
String baseId;
}
And I want to serialize List objs; To do it with jackson, I need to specify a list's elements real type, due to the java type erasure. This code will work:
List<Base> data = getData();
return new ObjectMapper().writerWithType(TypeFactory.collectionType(List.class, Base.class)).writeValueAsString(data);
Now, I want to serialize more complex class:
class Result{
List<Base> data;
}
How should I tell Jackson to properly serialize this class?
Just
new ObjectMapper().writeValueAsString(myResult);
The type of the list won't be lost due to type erasure in the same way it would be in the first example.
Note that for vanilla serialization of a list or generic list, it's not necessary to specify the list component types, as demonstrated in the example in the original question. All three of the following example serializations represent the List<Bar>
with the exact same JSON.
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;}
}
A typed writer is useful when serializing with additional type information. Note how the json1
and json3
outputs below differ.
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}
// ]
// ]
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With