仅在序列化过程中使用@JsonIgnore,而不是反序列化


325

我有一个发送到服务器或从服务器发送的用户对象。发送用户对象时,我不想将哈希密码发送给客户端。因此,我添加@JsonIgnore了password属性,但是这也阻止了将其反序列化为密码,这使得在没有密码的情况下很难注册用户。

我怎样才能只@JsonIgnore适用于序列化而不适用于反序列化?我使用的是Spring JSONView,因此对的控制并不多ObjectMapper

我尝试过的事情:

  1. 添加@JsonIgnore到属性
  2. @JsonIgnore仅添加getter方法

Answers:


481

确切的操作方法取决于您使用的Jackson版本。围绕1.9版进行了更改,在此之前,您可以通过添加@JsonIgnore到getter中来实现。

您尝试过的:

仅在getter方法上添加@JsonIgnore

执行此操作,然后@JsonPropertyJSON“密码”字段名称的特定注释添加到对象密码的setter方法中。

杰克逊(Jackson)的最新版本已为添加READ_ONLYWRITE_ONLY注释参数JsonProperty。因此,您还可以执行以下操作:

@JsonProperty(access = Access.WRITE_ONLY)
private String password;

可以在这里找到文档。


2
gist.github.com/thurloat/2510887 for Jackson JSON 仅在反序列化时忽略
Hadas

1
AFAIK,您仍然必须实现设置器并对其进行注释。我只想要获取器进行序列化。您所说的瞬态是什么?这是JPA注释的AFAIK
Matt Broekhuis 2014年

3
另外,请确保从字段本身中删除@JsonProperty,否则它将覆盖您的getter / setter注释
Anton Soradoi 2015年

15
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
米哈伊尔·巴瑟

1
Jackson注释2.5没有更高版本的功能。杰克逊(Jackson)批注2.6.3确实有
radiantRazor

98

为了做到这一点,我们需要做的是两个注释:

  1. @JsonIgnore
  2. @JsonProperty

使用@JsonIgnore类成员和其吸气剂,并@JsonProperty在它的制定者。示例示例将有助于实现此目的:

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;
    }
}

2
这是杰克逊2.6.4对我唯一有效的方法。我尽力使用@JsonProperty(access = Access.WRITE_ONLY),但对我而言不起作用。
cirovladimir '17

77

从2.6版开始:一种更直观的方法是com.fasterxml.jackson.annotation.JsonProperty在字段上使用注释:

@JsonProperty(access = Access.WRITE_ONLY)
private String myField;

即使存在吸气剂,该字段值也会从序列化中排除。

JavaDoc说:

/**
 * 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

如果您需要其他方法,请使用Access.READ_ONLY


1
我不明白为什么投票如此之少,这是解决此问题的一种优雅方法,就像一种魅力。无需注释getter,setter和field。只有字段。谢谢。
CROSP


可能是2.6+用户的最佳答案。
David Dossot '16

确保您没有使用org.codehaus.jackson.annotate导入。@DanielBeer的解决方案适用于Jackson 2.6.3。既然Jackson已经更新,这应该是公认的答案。
肯特·布尔

13

就我而言,我让Jackson从Spring MVC控制器返回的对象自动(反序列化)对象(我在Spring 4.1.6中使用@RestController)。我不得不使用com.fasterxml.jackson.annotation.JsonIgnore代替org.codehaus.jackson.annotate.JsonIgnore,否则,它什么也没做。


1
这是一个非常有用的答案,确实帮助我找到了为什么@JsonIgnore未被Jackson尊敬的原因……谢谢!
克林特·伊斯特伍德

2
"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
                }

4
将来甚至对代码的工作方式进行简短描述也可能会有所帮助。
KWILLIAMS'9

好的 !!您在这里尝试什么?获得更多选票?大声笑
Balaji Boggaram Ramanarayan '18 -10-10

0

解决此问题的另一种简便方法是allowSetters=true在批注中使用参数。这将允许将密码反序列化为您的dto,但不会将其序列化为使用包含对象的响应主体。

例:

@JsonIgnoreProperties(allowSetters = true, value = {"bar"})
class Pojo{
    String foo;
    String bar;
}

两者foobar都填充在对象中,但是只有foo被写入响应主体。


那是我的错误,我没有意识到您已经纠正了代码段。查看您的更改,看来我在Groovy中的多年写作吸引了我,并且我对Java的翻译有些粗糙。抱歉!
Dhandley
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.