@JsonIgnore和@Transient有什么区别?

25

在序列化和反序列化中,选用哪一种方法来跳过字段。

@JsonIgnore为什么要使用它,如果@Transient也可以跳过序列化和反序列化过程中的字段?

3个回答

38
两者的明显区别在于,@Transient 是用作 JPA 的一部分,如果将字段标记为@Transient,则可以忽略该字段不进行持久化。
@JsonIgnore 仅用于忽略标记字段的序列化和反序列化,即使使用 JPA 持久化,标记为 @JsonIgnore 的字段仍然可以持久化,但使用@Transient 标记的字段既不会被持久化也不会进行序列化或反序列化。

5
为什么 @Transient 字段不会被 Jackson 进行序列化/反序列化? - Erik Gillespie
2
有没有一种方法可以让序列化但阻止持久化? - Zain Elabidine
@ErikGillespie 我猜这是因为注解应该与Java中的“transient”关键字类似。https://en.wikibooks.org/wiki/Java_Programming/Keywords/transient#:~:text=transient%20is%20a%20Java%20keyword,object%20state%20to%20serial%20bytes. - java-addict301

3
我们应该区分 javax.persistence.Transientjava.beans.Transient。前者表示JPA忽略属性的持久性,不影响编组。Jackson在编组期间将后者视为JsonIgnore,如JacksonAnnotationIntrospector#_isIgnorable(Annotated)中所示。
protected boolean _isIgnorable(Annotated a)
{
    JsonIgnore ann = _findAnnotation(a, JsonIgnore.class);
    if (ann != null) {
        return ann.value();
    }
    if (_java7Helper != null) {
        Boolean b = _java7Helper.findTransient(a);
        if (b != null) {
            return b.booleanValue();
        }
    }
    return false;
}

Java7SupportImpl#findTransient(Annotated) 的查找目标是 java.beans.Transient


请注意,Jackson在处理字段上的@javax.persistence.Transient注释时与处理方法上的@java.beans.Transient注释方式相同 -- 即与@JsonIgnore相同 -- 如果您注册了Hibernate5Module。该类位于jackson-datatype-hibernate5中。可能还有其他数据类型库也会执行相同的操作。 - Matthew Read

3

@Transient是Java语言中transient关键字的一个比喻。当用于变量时,该变量不会被序列化。

示例:

public class Person {
    String name;
    int age;
    String password;

    public Person(String name, int age, String password) {
        this.name = name;
        this.age = age;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

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

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

}

public void serializationTest() throws JsonProcessingException {

    Person aPerson = new Person("Demonte", 37, "bestKeptSecret1995");
    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(aPerson);

    System.out.println(json);
}

通过为 getPassword() 添加注释(记住序列化时的getter)@Transient将会产生

{"name":"Demonte","age":37}

现在,如果您重新访问Person类代码并删除@Transient,将transient添加到password变量中,并且还要向Jackson映射程序添加一个功能以告诉它如何处理标记为transient的字段。
transient String password;

并且

mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);

(请记住,Jackson在序列化时使用getter而不是直接使用成员变量)然后您将获得相同的输出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接