@JsonIgnore vs @Transient -difference?


哪个

用于跳过序列化和反序列化字段。

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

两者之间的明显区别在于,@Transient用作 JPA 的一部分,以忽略字段的持久化,如果该字段被标记为 @Transient

其中 as @JsonIgnore 仅用于忽略标记的字段,使其无法序列化、反序列化到 JSON 和从 JSON 进行反序列化。

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

我们应该区分javax.persistence.Transientjava.beans.Transient。正如 @shazin 和 @Abhishek Kumar 所提到的,前者向 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.

@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()(记住序列化的 getters),@Transient将产生

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

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

transient String password;

mapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);

(请记住,杰克逊直接使用getter而不是成员进行序列化)然后您将获得相同的输出。

最新更新