问题
By default, Jackson is using java.util.ArrayList
to deserialise a JSON array. Instead of this, I want to use a custom implementation. For example, Guava ImmutableList
if value is present, or Collection.emptyList()
if JSON array is empty or null.
I want to configure this globally for ObjectMapper
. Is there an easy way to do this?
PS: My Jackson version is 2.9.7
回答1:
General solution is to use custom module. You can define classes you would like to use for collections. For Guava there is a Maven module:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-guava</artifactId>
<version>x.y.z</version>
</dependency>
Now, you can register your new module:
ObjectMapper mapper = new ObjectMapper();
// register module with object mapper
mapper.registerModule(new GuavaModule());
Now, you can define in your POJO
you want to have immutable implementation of the list.
class Pojo {
private ImmutableList<Integer> ints;
public ImmutableList<Integer> getInts() {
return ints;
}
public void setInts(ImmutableList<Integer> ints) {
this.ints = ints;
}
@Override
public String toString() {
return "Pojo{" +
"ints=" + ints + " " + ints.getClass() + '}';
}
}
and below example:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new GuavaModule());
String json = "{\"ints\":[1,2,3,4]}";
System.out.println(mapper.readValue(json, Pojo.class));
prints:
Pojo{ints=[1, 2, 3, 4] class com.google.common.collect.RegularImmutableList}
If you do not want to tie your POJO
classes with List
implementation you need to add some extra configuration using SimpleModule
class. So, your POJO
looks like below:
class Pojo {
private List<Integer> ints;
public List<Integer> getInts() {
return ints;
}
public void setInts(List<Integer> ints) {
this.ints = ints;
}
@Override
public String toString() {
return "Pojo{" +
"ints=" + ints + " " + ints.getClass() + '}';
}
}
and your example looks like this:
SimpleModule useImmutableList = new SimpleModule("UseImmutableList");
useImmutableList.addAbstractTypeMapping(List.class, ImmutableList.class);
GuavaModule module = new GuavaModule();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
mapper.registerModule(useImmutableList);
String json = "{\"ints\":[1,2,3,4]}";
System.out.println(mapper.readValue(json, Pojo.class));
Above code prints:
Pojo{ints=[1, 2, 3, 4] class com.google.common.collect.RegularImmutableList}
When you remove extra SimpleModule
above code prints:
Pojo{ints=[1, 2, 3, 4] class java.util.ArrayList}
I do not see any point to use Collections.emptyList()
in case it is empty. Guava
's module uses RegularImmutableList
for not empty and empty arrays.
For converting null -> empty
see this question:
- Jackson deserializer - change null collection to empty one
but I recommend to set it to empty
in POJO
like below:
private List<Integer> ints = Collections.emptyList();
回答2:
I don't think that easy way exists, because CollectionDeserializer
create instance of collection before parse. So, for this purposes you need to create your custom deserializer.
But I'm not sure=))
来源:https://stackoverflow.com/questions/54255852/jackson-global-settings-to-deserialise-array-to-custom-list-implementation