@JsonIgnore vs @Transient -difference?

时间:2015-04-21 03:23:54

标签: java hibernate jpa jackson

使用哪一个跳过字段进行序列化和反序列化。

@JsonIgnore 为什么我们应该使用它,如果@Transient也从序列化和反序列化过程中跳过该字段?

3 个答案:

答案 0 :(得分:16)

两者之间的明显区别是@Transient被用作JPA的一部分,如果字段标记为@Transient则忽略该字段的持久性。

其中@JsonIgnore仅用于忽略标记字段的序列化,反序列化为JSON和从JSON反序列化。

这意味着标记为@JsonIgnore的字段仍然可以保留在JPA持久性中,因为标记为@Transient的字段既不会被持久化也不会被序列化,反序列化。

答案 1 :(得分:3)

我们应该区分javax.persistence.Transientjava.beans.Transient。正如@shazin和@Abhishek Kumar所提到的,前者向JPA发出信号,表示JPA将忽略该属性以保持持久性,并且不会影响编组。杰克逊在编组期间将后者与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的地方。

答案 2 :(得分:0)

@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() (记住用于序列化的吸气剂) @Transient将产生

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

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

的字段
transient String password;

mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);

(记住Jackson会直接使用getter而不是成员进行序列化),那么您将获得相同的输出。