ChatGPT解决这个技术问题 Extra ChatGPT

仅在序列化期间使用@JsonIgnore,而不是反序列化

我有一个发送到服务器和从服务器发送的用户对象。当我发送用户对象时,我不想将散列密码发送给客户端。因此,我在密码属性上添加了 @JsonIgnore,但这也阻止了它被反序列化为密码,这使得在没有密码时很难注册用户。

我怎样才能让 @JsonIgnore 应用于序列化而不是反序列化?我正在使用 Spring JSONView,因此我无法控制 ObjectMapper

我尝试过的事情:

将@JsonIgnore 添加到属性中 仅在getter 方法上添加@JsonIgnore


M
Maifee Ul Asad

具体如何执行此操作取决于您使用的 Jackson 版本。这在 1.9 版本周围发生了变化,在此之前,您可以通过将 @JsonIgnore 添加到 getter 来实现。

您尝试过的:

仅在 getter 方法上添加 @JsonIgnore

执行此操作,将您的 JSON“密码”字段名称的特定 @JsonProperty 注释添加到对象密码的 setter 方法。

更新的 Jackson 版本为 JsonProperty 添加了 READ_ONLYWRITE_ONLY 注释参数。因此,您还可以执行以下操作:

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

可以在 here 中找到文档。


gist.github.com/thurloat/2510887 仅用于 反序列化 上的 Jackson JSON 忽略
AFAIK 你仍然必须实现设置器并对其进行注释。我只想要序列化的吸气剂。你说的瞬态是什么?这是一个 JPA 注释 AFAIK
另外,请确保从字段本身中删除 @JsonProperty 否则它将覆盖您的 getter/setter 注释
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
Jackson-annotations 2.5 没有后面的功能。 Jackson-annotations 2.6.3 确实
S
Sae1962

为了做到这一点,我们只需要两个注解:

@JsonIgnore @JsonProperty

在类成员及其 getter 上使用 @JsonIgnore,在其 setter 上使用 @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.6.4 唯一对我有用的东西。我尽力使用 @JsonProperty(access = Access.WRITE_ONLY) 但它对我不起作用。
A
Aaron Kurtzhals

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

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

即使存在 getter,字段值也会从序列化中排除。

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


我不明白为什么赞成票这么少,这是解决这个问题的优雅方法,就像一个魅力。无需注释 getter、setter 和 field。唯一的领域。谢谢。
这从 2.6 版开始可用,请参阅 fasterxml.github.io/jackson-annotations/javadoc/2.6/com/…
可能是 2.6+ 用户的最佳答案。
确保您没有使用 org.codehaus.jackson.annotate 导入。 @DanielBeer 的解决方案适用于 Jackson 2.6.3。既然杰克逊已经更新,这应该是公认的答案。
S
Sae1962

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


这是一个非常有用的答案,它真的帮助我找到了为什么@JsonIgnore 没有被杰克逊尊重的原因......谢谢!
d
dkb

处理此问题的另一种简单方法是在注释中使用参数 allowSetters=true。这将允许将密码反序列化到您的 dto 中,但不会将其序列化为使用包含对象的响应正文。

例子:

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

foobar 都填充在对象中,但只有 foo 写入响应正文。


那是我的错误,我没有意识到你已经纠正了这个片段。查看您的更改,看来我在 Groovy 中多年的写作让我受益匪浅,而且我对 Java 的翻译有点粗糙。对不起!
M
Musa
"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
                }

将来对代码的工作原理进行简要描述可能会有所帮助。
好吧 !!你在这里尝试什么?获得更多选票?哈哈
K
Kedar Gokhale

您可以在类级别使用 @JsonIgnoreProperties 并将您想要在 json 中的变量放入“值”参数中。对我来说很好。

@JsonIgnoreProperties(value = { "myVariable1","myVariable2" })
public class MyClass {
      private int myVariable1;,
      private int myVariable2;
}

S
Swapnil Ingawale

你也可以这样做:

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

它对我有用


它会完全忽略。这不是所问的。 JsonIgnore 优先于 JsonProperty。
C
Collin Krawll

我正在寻找类似的东西。我仍然希望我的属性序列化,但想使用不同的 getter 更改值。在下面的示例中,我正在反序列化真实密码,但序列化为掩码密码。这是如何做到的:

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