187

I have an entity class with a password field:

class User {
    private String password;

    //setter, getter..
}

I want this field to be skipped during serialization. But it should still be able to deserialize. This is needed, so that the client can send me a new password, but is not able to read the current one.

How do I accomplish this with Jackson?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
weekens
  • 8,064
  • 6
  • 45
  • 62
  • 1
    You don't want to serialize it, but you want to be able to deserialize it? That's impossible, I would say. If you don't put a cookie in a box, you will not be able to retrieve it from this box. – Alexis Dufrenoy Feb 02 '12 at 13:26
  • 1
    @Traroth: but I can put a NEW cookie. I'm just searching for a convenient annotation, but this can be surely done by hand. – weekens Feb 02 '12 at 13:39
  • 8
    Quick comment: it is completely possible, technically, to have a setter that is used (even private ones are auto-detected), and just omit accessor (no public field or getter). It is also possible to add `@JsonIgnore` on getter, but `@JsonProperty` on setter, in which case things is not serialized, but can be deserialized. – StaxMan Feb 03 '12 at 18:24
  • 4
    Would you mind accepting an answer on this question? (A couple of your others are a few years old & still unaccepted too... Please consider review!) :) Full disclosure - I have no answers on any of these questions. – Barett Nov 09 '16 at 21:06
  • 1
    Does this answer your question? [Only using @JsonIgnore during serialization, but not deserialization](https://stackoverflow.com/questions/12505141/only-using-jsonignore-during-serialization-but-not-deserialization) – kulsin Oct 01 '20 at 15:09
  • An option to dynamically ignore fields during the serialization: https://stackoverflow.com/a/74594018/8315708 – Taras Shpek Nov 27 '22 at 21:47

9 Answers9

216

You can mark it as @JsonIgnore.

With 1.9, you can add @JsonIgnore for getter, @JsonProperty for setter, to make it deserialize but not serialize.

narendra-choudhary
  • 4,582
  • 4
  • 38
  • 58
Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125
  • 6
    @JsonIgnore prevents deserialization as well. For transient - I'll check it out. – weekens Feb 02 '12 at 14:20
  • 108
    With 1.9, you can add `@JsonIgnore` for getter, `@JsonProperty` for setter, to make it deserialize but not serialize. – StaxMan Feb 03 '12 at 00:59
  • StaxMan's comment should be the answer, shouldn't it? Why is it still a comment then...!..? – Saravanabalagi Ramachandran Oct 22 '15 at 14:04
  • transient doesnt seem to work for me, i marked the field "transient" that i donot want it to be serilized/deserialized. – rohith Mar 03 '16 at 14:53
  • This answer previously suggested using `transient` (as in `private transient String password;`) but [transient fields with public getters are ignored](https://github.com/FasterXML/jackson-databind/issues/296) unless [MapperFeature.PROPAGATE_TRANSIENT_MARKER](https://fasterxml.github.io/jackson-databind/javadoc/2.8/com/fasterxml/jackson/databind/MapperFeature.html#PROPAGATE_TRANSIENT_MARKER) is enabled. – tom Oct 11 '17 at 22:58
  • `@JsonIgnore` on field and getter and `@JsonProperty` on setter deserializes and does not serialize a singular property. However when I do same on List field it does not deserialize either? Any solutions to this? – Farrukh Najmi Oct 20 '17 at 00:26
102

Illustrating what StaxMan has stated, this works for me

private String password;

@JsonIgnore
public String getPassword() {
    return password;
}

@JsonProperty
public void setPassword(String password) {
    this.password = password;
}
Robert Jack Will
  • 10,333
  • 1
  • 21
  • 29
Gary
  • 2,186
  • 2
  • 15
  • 11
41

Starting with Jackson 2.6, a property can be marked as read- or write-only. It's simpler than hacking the annotations on both accessors and keeps all the information in one place:

public class User {
    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String password;
}
Frank Pavageau
  • 11,477
  • 1
  • 43
  • 53
  • This is an awesome solution, simple, working. Thanks. – dhqvinh Oct 22 '19 at 21:59
  • Yes. Thank you. For some reason, the normal @ JsonProperty on the setter and @ JsonIgnore on the getter would absolutely not work for me. I can't figure out why, but this nailed it. Thank you. – Forrest Jan 18 '21 at 23:31
  • StackOverflow should come up with multiple upvotes, everytime I forget this annotation, SO brings back to your answer, thanks, pal. – Neeraj Jain Jan 19 '21 at 10:29
40

The easy way is to annotate your getters and setters.

Here is the original example modified to exclude the plain text password, but then annotate a new method that just returns the password field as encrypted text.

class User {

    private String password;

    public void setPassword(String password) {
        this.password = password;
    }

    @JsonIgnore
    public String getPassword() {
        return password;
    }

    @JsonProperty("password")
    public String getEncryptedPassword() {
        // encryption logic
    }
}
Community
  • 1
  • 1
Joe Allen
  • 401
  • 4
  • 3
19

Aside from @JsonIgnore, there are a couple of other possibilities:

  • Use JSON Views to filter out fields conditionally (by default, not used for deserialization; in 2.0 will be available but you can use different view on serialization, deserialization)
  • @JsonIgnoreProperties on class may be useful
Sinister Beard
  • 3,570
  • 12
  • 59
  • 95
StaxMan
  • 113,358
  • 34
  • 211
  • 239
13

transient is the solution for me. thanks! it's native to Java and avoids you to add another framework-specific annotation.

maxxyme
  • 2,164
  • 5
  • 31
  • 48
  • 2
    That works if your attribute is really transient, not ORM involved, for example....Found @JsonIgnore to be more interesting in my case, though I would be locked to jackson, but it's a good tradeoff – Joao Pereira Oct 25 '13 at 19:36
  • 3
    You don't have to be locked to jackson if you create your own annotation and have it annotated by JsonIgnore and JacksonAnnotationsInside. That way, if you change serializers, you only have to change your own annotation. – DavidA Jun 19 '14 at 22:10
5

Jackson has a class named SimpleBeanPropertyFilter that helps to filter fields during serialization and deserialization; not globally. I think that's what you wanted.

@JsonFilter("custom_serializer")
class User {
    private String password;

    //setter, getter..
}

Then in your code:

String[] fieldsToSkip = new String[] { "password" };

ObjectMapper mapper = new ObjectMapper();

final SimpleFilterProvider filter = new SimpleFilterProvider();
filter.addFilter("custom_serializer",
            SimpleBeanPropertyFilter.serializeAllExcept(fieldsToSkip));

mapper.setFilters(filter);

String jsonStr = mapper.writeValueAsString(currentUser);

This will prevent password field to get serialized. Also you will be able to deserialize password fields as it is. Just make sure no filters are applied on the ObjectMapper object.

ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(yourJsonStr, User.class);    // user object does have non-null password field
krhitesh
  • 777
  • 9
  • 14
4

One should ask why you would want a public getter method for the password. Hibernate, or any other ORM framework, will do with a private getter method. For checking whether the password is correct, you can use

public boolean checkPassword(String password){
  return this.password.equals(anyHashingMethod(password));
}
Albert Waninge
  • 319
  • 1
  • 10
  • I actually think this is the best way to think about the solution. It makes more sense to make things you need private and control them from the object itself. – arcynum Jan 17 '17 at 00:29
1

set variable as

@JsonIgnore

This allows variable to get skipped by json serializer

Pravin Bansal
  • 4,315
  • 1
  • 28
  • 19