Anne Maier
Anne Maier

Reputation: 319

Jackson: ignore empty object

If the value of the field name in the inner class is null, then

{"id": 123, "inner": {}}

is returned as a response. However, if the value to inner is returned as {}, the key-value pair

"inner": {}

should be ignored entirely, so the response is

{"id": 123}

. How can this be achieved? I thought it could be achieved with @JsonInclude(JsonInclude.Include.NON_NULL) but it did not solve the problem.

@RestController
public class ItemController {
    @Autowired
    ItemService itemService;

    @GetMapping("/item")
    public Item getItem() {
        return itemService.getItem(); // {"id": 123,"inner": {}} is returned but should be {"id": 123}
    }
}
@Service
public class ItemService {
    public Item getItem() {
        Item.Inner inner = new Item.Inner();
        Item item = new Item();
        item.setInner(inner);
        item.setId(123);

        return item;
    }
}
@Data
public class Item {
    private int id;
    private Inner inner;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    @Data
    public static class Inner {
        private String name;
    }
}

Upvotes: 0

Views: 1326

Answers (3)

Kumaresh Babu N S
Kumaresh Babu N S

Reputation: 1698

By using JsonInclude annotation, it will remove the empty values.

@Data
@JsonInclude(JsonInclude.Include.NOT_NULL)
public class Item {
    private int id;
    private Inner inner;

    public static class Inner {
        private String name;
    }
}

Upvotes: 0

Nemanja
Nemanja

Reputation: 3669

You can use @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = Inner .class) on Inner field in Item class, but to make this work you need to override hashcode and equals method in Item class.

Basically, the equals method in Inner class will be called when deciding whether or not inner object should be excluded or not. If equals returns true, then the object will be excluded from response. So make the method match anything you want to filter out and return false for anything that should be written out normally.

You can read more details here

For your particular case, the following code should work :

@Data
public class Item {
    private int id;

    @JsonInclude(value = JsonInclude.Include.CUSTOM, valueFilter = Inner .class)
    private Inner inner;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Inner getInner() {
        return inner;
    }

    public void setInner(Inner inner) {
        this.inner = inner;
    }

    
    @Data
    public static class Inner {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Inner inner = (Inner) o;
            return Objects.equals(name, inner.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    }
}

NOTE: @JsonInclude(JsonInclude.Include.NON_NULL) will ignore null fields, so if you put it on class level for Inner class you will get response like this (it will ignore name field in Inner class since it's value is null) :

{
    "id": 123,
    "inner": {}
}

That will also not work if you put it on class level for class Item since your Inner object is not null, it's empty object, so that will produce this:

{
    "id": 123,
    "inner": {
        "name": null
    }
}

Upvotes: 2

Harish Dalmia
Harish Dalmia

Reputation: 138

Please try with below at the class level.

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)

Thank you

Upvotes: 0

Related Questions