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 @JsonIgnore to the property Add @JsonIgnore on the getter method only
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.
In 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;
}
}
Since 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=true
in 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": "klaudi2012@gmail.com",
"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
}
You 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
I 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;
}
}
Success story sharing
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)