相关文章推荐
怕老婆的红金鱼  ·  Choose the right ...·  1 年前    · 
性感的夕阳  ·  (二) ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams @JsonProperty(value="homes") @JsonDeserialize(as=HashSet.class, contentAs=HomeImpl.class) private Collection<Home> homes = new ArrayList<Home>();

If request contains null as request property:

"homes": null

then homes is set to null. What I want to do is to set homes to empty list. Do I need to write special deserializer for this or is there one for collections? What I tried is this deserializer but it looks ugly (it's not generic and uses implementation instead of interface).

public class NotNullCollectionDeserializer extends JsonDeserializer<Collection<HomeImpl>> {
  @Override
  public Collection<HomeImpl> deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
    return jsonParser.readValueAs(new TypeReference<Collection<HomeImpl>>(){});
  @Override
  public Collection<HomeImpl> getNullValue() {
    return Collections.emptyList();

So few questions:

  • Is there some jackson property that changes null to empty collection during deserialization?
  • If no for the first point - do I need to write deserializer for this? If yes, can I write generic one?
  • As of Jackson 2.9, it looks like null-handling for specific properties can be configured with @JsonSetter, for example:

    @JsonSetter(nulls = Nulls.AS_EMPTY)
    public void setStrings(List<String> strings) {
        this.strings = strings;
    

    Similar configuration can also be applied globally for collections:

    ObjectMapper mapper = objectMapperBuilder()
        .changeDefaultNullHandling(n -> n.withContentNulls(Nulls.AS_EMPTY))
        .build();
    

    Or by type:

    ObjectMapper mapper = objectMapperBuilder()
        .withConfigOverride(List.class,
            o -> o.setNullHandling(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)))
        .build();
    

    I haven't been able to try the feature out, so this is based on the feature discussion and examination of unit tests. YMMV.

    To be clear, there is not method objectMapperBuilder() in Jackson 2.9. There is jsonMapperBuilder() in 2.10, which is just helper method in Jackson tests and it just returns JsonMapper.builder(), where JsonMapper is a new helper class introduced in 2.10. In 2.9 the defaults can be configured using ObjectMapper, like this mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY)); or for specific type: mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));. – Ruslan Stelmachenko Jul 10, 2019 at 9:58 + @RuslanStelmachenko forContentNulls is for null array elements, the forValueNulls is needed for entire null array: mapper.configOverride(List.class).setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY)); – Roman Sinyakov Oct 9, 2020 at 8:56 Note that per the Javadoc, this only works if the value is explicitly set to null, rather than omitted from the JSON. {"homes": null} vs. {}. – M. Justin Feb 2, 2021 at 0:43 @M.Justin You are right. So question is how to get empty collection after deserialization if the attribute is completely omitted in json (reqeust). – sasynkamil Dec 22, 2022 at 8:07 @sasynkamil initialize it with new keyword on field level, it won't be overridden by jackson – Conrad Jan 5 at 13:44

    I also couldn't find a Jackson property or annotation for this. So I'll have to answer no to the first question. But I would recommend a simple setter instead of the special deserializer :

    public class Entity {
        @JsonDeserialize(contentAs = HomeImpl.class)
        private Collection<Home> homes = new ArrayList<>();
        public void setHomes(List<Home> homes) {
            if (homes != null)
                this.homes = homes;
    

    This is generic as it only uses the Home interface instead of HomeImpl. You don't need @JsonProperty as Jackson will associate setHomes and homes.

    One thing that drove me crazy: You cannot combine @JsonDeserialize and @JsonSetter(nulls=Nulls.AS_EMPTY). You'll have to implement JsonDeserializer#getNullValue() and remove @JsonSetter – Ich Nov 18, 2020 at 20:45

    What worked for me was simply to remove the setter and make the attribute final. jackson 2 will then use the getter to modify the list.

    public class Entity {
      @JsonProperty(value="homes")
      @JsonDeserialize(as=HashSet.class, contentAs=HomeImpl.class)
      private final Collection<Home> homes = new ArrayList<Home>();
      public List<Home> getHomes() {
         return homes;
    

    The responsible feature is USE_GETTERS_AS_SETTERS which is turned on by default: https://github.com/FasterXML/jackson-databind/wiki/Mapper-Features

    I think the cleanest solution in my case which is working as expected (get empty list instead of null after deserialization) in both cases:

  • property is omitted in the json (request)
  • property is explicitly set to null in the json (request)
  • @Valid // javax.validation
    @Schema(required = false) // swagger.v3 
    @JsonProperty(required = false, defaultValue = "") // jackson 2.13
    private List<@NotEmpty @Size(max = 100) String> actions = new ArrayList<>();
    public List<String> getActions() {
        return actions;
    @JsonSetter(nulls = Nulls.AS_EMPTY)
    public void setActions(List<String> actions) {
        this.actions = actions;
    

    Notes:

  • when property explicitly set to null: used default annotations
  • when property omitted: added initialization = new ArrayList<>();
  • when used e.g. java validation, then this solution is needed just for optional (required = false) lists
  • Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.