用于跳过序列化和反序列化字段。
@JsonIgnore如果@Transient也跳过序列化和反序列化过程中的字段,我们为什么要使用它?
两者之间的明显区别在于,@Transient
用作 JPA 的一部分,以忽略字段的持久化,如果该字段被标记为 @Transient
。
其中 as @JsonIgnore
仅用于忽略标记的字段,使其无法序列化、反序列化到 JSON 和从 JSON 进行反序列化。
这意味着标记为 @JsonIgnore
的字段仍然可以保留在 JPA 持久性中,而标记为 @Transient
的字段既不会被持久化,也不会被序列化、反序列化。
我们应该区分javax.persistence.Transient
和java.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而不是成员进行序列化)然后您将获得相同的输出。