I have a user object that is sent to and from the server. When I send out the user object, I don't want to send the hashed password to the client. So, I added @JsonIgnore on the password property, but this also blocks it from being deserialized into the password that makes it hard to sign up users when they don't have a password.
How can I only get @JsonIgnore to apply to serialization and not deserialization? I'm using Spring JSONView, so I don't have a ton of control over the ObjectMapper.
Things I've tried:
- Add
@JsonIgnoreto the property - Add
@JsonIgnoreon the getter method only
9 Answers
Exactly how to do this depends on the version of Jackson that you're using. This changed around version 1.9, before that, you could do this by adding @JsonIgnore to the getter.
Which you've tried:
Add @JsonIgnore on the getter method only
Do this, and also add a specific @JsonProperty annotation for your JSON "password" field name to the setter method for the password on your object.
More recent versions of Jackson have added READ_ONLY and WRITE_ONLY annotation arguments for JsonProperty. So you could also do something like:
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY) private String password; Docs can be found here.
10In order to accomplish this, all that we need is two annotations:
@JsonIgnore@JsonProperty
Use @JsonIgnore on the class member and its getter, and @JsonProperty on its setter. A sample illustration would help to do this:
class User { // More fields here @JsonIgnore private String password; @JsonIgnore public String getPassword() { return password; } @JsonProperty public void setPassword(final String password) { this.password = password; } } 1Since version 2.6: a more intuitive way is to use the com.fasterxml.jackson.annotation.JsonProperty annotation on the field:
@JsonProperty(access = Access.WRITE_ONLY) private String myField; Even if a getter exists, the field value is excluded from serialization.
JavaDoc says:
/** * Access setting that means that the property may only be written (set) * for deserialization, * but will not be read (get) on serialization, that is, the value of the property * is not included in serialization. */ WRITE_ONLY In case you need it the other way around, just use Access.READ_ONLY.
In my case, I have Jackson automatically (de)serializing objects that I return from a Spring MVC controller (I am using @RestController with Spring 4.1.6). I had to use com.fasterxml.jackson.annotation.JsonIgnore instead of org.codehaus.jackson.annotate.JsonIgnore, as otherwise, it simply did nothing.
Another easy way to handle this is to use the argument allowSetters=truein the annotation. This will allow the password to be deserialized into your dto but it will not serialize it into a response body that uses contains object.
example:
@JsonIgnoreProperties(allowSetters = true, value = {"bar"}) class Pojo{ String foo; String bar; } Both foo and bar are populated in the object, but only foo is written into a response body.
"user": { "firstName": "Musa", "lastName": "Aliyev", "email": "", "passwordIn": "98989898", (or encoded version in front if we not using https) "country": "Azeribaijan", "phone": "+994707702747" } @CrossOrigin(methods=RequestMethod.POST) @RequestMapping("/public/register") public @ResponseBody MsgKit registerNewUsert(@RequestBody User u){ root.registerUser(u); return new MsgKit("registered"); } @Service @Transactional public class RootBsn { @Autowired UserRepository userRepo; public void registerUser(User u) throws Exception{ u.setPassword(u.getPasswordIn()); //Generate some salt and setPassword (encoded - salt+password) User u=userRepo.save(u); System.out.println("Registration information saved"); } } @Entity @JsonIgnoreProperties({"recordDate","modificationDate","status","createdBy","modifiedBy","salt","password"}) public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.AUTO) private Long id; private String country; @Column(name="CREATED_BY") private String createdBy; private String email; @Column(name="FIRST_NAME") private String firstName; @Column(name="LAST_LOGIN_DATE") private Timestamp lastLoginDate; @Column(name="LAST_NAME") private String lastName; @Column(name="MODIFICATION_DATE") private Timestamp modificationDate; @Column(name="MODIFIED_BY") private String modifiedBy; private String password; @Transient private String passwordIn; private String phone; @Column(name="RECORD_DATE") private Timestamp recordDate; private String salt; private String status; @Column(name="USER_STATUS") private String userStatus; public User() { } // getters and setters } 2You can use @JsonIgnoreProperties at class level and put variables you want to igonre in json in "value" parameter.Worked for me fine.
@JsonIgnoreProperties(value = { "myVariable1","myVariable2" }) public class MyClass { private int myVariable1;, private int myVariable2; } You can also do like:
@JsonIgnore @JsonProperty(access = Access.WRITE_ONLY) private String password; It's worked for me
1I was looking for something similar. I still wanted my property serialized but wanted to alter the value using a different getter. In the below example, I'm deserializing the real password but serializing to a masked password. Here's how to do it:
public class User() { private static final String PASSWORD_MASK = "*********"; @JsonIgnore private String password; @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) public String setPassword(String password) { if (!password.equals(PASSWORD_MASK) { this.password = password; } } public String getPassword() { return password; } @JsonProperty("password") public String getPasswordMasked() { return PASSWORD_MASK; } }