1

I have these two calsses Human and User and they look like :

public class User{

    @JsonView(ExternalCategoriesViews.CustomCategoryExternalView.class)
    protected Long id;

    @JsonView(ExternalCategoriesViews.CustomCategoryExternalView.class)
    protected String firstname;

    @JsonView(ExternalCategoriesViews.CustomCategoryExternalView.class)
    protected String lastname;
    protected String email;
    protected String address;
    protected String postalCode;
    @JsonView(ExternalCategoriesViews.CustomCategoryExternalView.class)
    protected String city;
    protected String country;

    public User(Long id, String firstname, String lastname, String email, String address,
        String postalCode, String city, String country) {
        this.id = id;
        this.firstname = firstname;
        this.lastname = lastname;
        this.email = email;
        this.address = address;
        this.postalCode = postalCode;
        this.city = city;
        this.country = country;
    }

}
public class Human extends User {

    String sex;
    @JsonView({ExternalCategoriesViews.CustomCategoryExternalView.class})
    String salary;

    public Human(Long id, String firstname, String lastname, String email, String address,
        String postalCode, String city, String country, String sex, String salary) {
        super(id, firstname, lastname, email, address, postalCode, city, country);
        this.sex = sex;
        this.salary = salary;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getSalary() {
        return salary;
    }

    public void setSalary(String salary) {
        this.salary = salary;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        if (!super.equals(o)) {
            return false;
        }
        Human human = (Human) o;
        return Objects.equals(salary, human.salary);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), salary);
    }
}

And I have a controller that returns Human.

@RequestMapping(method = RequestMethod.GET,
    value = "/test",
    produces = MediaType.APPLICATION_JSON + "; charset=UTF-8")
@ResponseBody
@JsonView(ExternalCategoriesViews.CustomCategoryExternalView.class)
public Human getCustomCategory1() {
    Human n = new Human(1L,"first name","last name", "w@c.c","address","qwe","city","country","male","12000");
    return n;
}

and I have this class for JsonView:

public class ExternalCategoriesViews {
    public interface CustomCategoryExternalView {
    }
}

The issue here is that what I'm anticipating is to get a response without "sex" property, as it's not annotated with @JsonView. so the response should not contain it but it's not the case, because I'm still seeing it.

I noticed that if I remove the getSex() getter then the "sex" property will disappear from the response so I can say @JsonView works.

But unfortunately, I can't get rid of the getter.

And then I understand that @JsonView() uses reflection to access private and protected properties. As soon as you delete the getter, Jackson doesn't know how to serialize/deserialize the properties, so without getters @JsonView() will work properly as it can't reach properties, and only those annotated with @JsonView() will be considerd in the serialization.

My question is, how to make this "sex" property disappear from the response(make @JsonView() work properly) without removing the getter?

João Dias
  • 16,277
  • 6
  • 33
  • 45
bashar
  • 135
  • 2
  • 11

1 Answers1

0

If you never want sex property to be available in the JSON response, just use @JsonIgnore as follows:

public class Human extends User {

    @JsonIgnore
    String sex;
    
    @JsonView({ExternalCategoriesViews.CustomCategoryExternalView.class})
    String salary;

    (...)
}

This means that sex will be ignore for serialization and deserialization. If you just want it to be ignored while serializing the object to JSON, then you can use @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) as follows:

public class Human extends User {

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    String sex;
    
    @JsonView({ExternalCategoriesViews.CustomCategoryExternalView.class})
    String salary;

    (...)
}

You can read more about this in the following reference documentation:


Given that you want to expose it in some Controllers and not it others you need another JsonView for this:

public class ExternalCategoriesViews {
    public interface CustomCategoryExternalView {
    }
    public interface AnotherCustomCategoryExternalView {
    }
}
public class Human extends User {

    @JsonView({ExternalCategoriesViews.AnotherCustomCategoryExternalView.class})
    String sex;

    @JsonView({ExternalCategoriesViews.CustomCategoryExternalView.class})
    String salary;

    (...)
}
João Dias
  • 16,277
  • 6
  • 33
  • 45
  • what if I have a new another controller, and in the new controller I need to return the response with "sex" ?? – bashar Nov 21 '21 at 13:56
  • Then you need another `JsonView` to be used on that controller and that you should also use to annotate `sex`. In this case, you can't use `@JsonProperty` or `@JsonIgnore`. – João Dias Nov 21 '21 at 13:58
  • but as I said above, @JsonView isn't working for me if I have getter for `sex` in `Human` class – bashar Nov 21 '21 at 14:03
  • You keep the getter as you should and everything should work. I've edited my answer. Please check it. On another topic please avoid doing this in the future. Coming up with new requirements once your question has been correctly answered. In these cases create a new question, otherwise, no question will ever be "closed". Thanks! – João Dias Nov 21 '21 at 14:56
  • But this was my question, I need to make @JsonView work (not using @JsonIgnore). As I descriped above when I add getter it's not working, and when I remove the getter then it's working. You are saying it should but it's not, and this is why I'm asking, I know it should but if it's not then what I'm missing here ?? – bashar Nov 21 '21 at 20:13
  • "The issue here is that what I'm anticipating is to get a response without "sex" property, as it's not annotated with @JsonView. so the response should not contain it but it's not the case, because I'm still seeing it.". This is how you described your issue. This does not mean that `@JsonView` does not work. On the contrary. The issue is that in your code you have no `@JsonView` in your `sex` property and thus it is always serialized. If you remove the getter it is not serialized, but that is a consequence of how Jackson accesses the data to be serialized. – João Dias Nov 21 '21 at 20:24
  • Can I ask why the unupvote? Was my answer not helpful at all that led you to unupvote it? – João Dias Nov 22 '21 at 10:04