Jackson教程
忽略、不序列化字段

在上一篇中,我们学习了如何忽略值为null的字段《Jackson忽略null字段的3种方法》。

相对于忽略null字段,在实际应用中,忽略某些字段的序列化可能更为常见。

Jackson对于如何序列化字段、过滤字段的方法多种多样,非常丰富,这一节先来了解一下3种简单的方法。

本篇内容基于Jackson 2.11.2版本,马上开始学习吧。

使用JsonIgnore注解忽略单个字段

为字段添加@JsonIgnore注解,可以忽略该字段的序列化和反序列化。

public class ArticleIgnore {
 
	private String title;
	@JsonIgnore
	private String summary;
	private String content;
	@JsonIgnore
	private String author;
 
	// 省略setter、getter方法
 
	@Override
	public String toString() {
		return "ArticleIgnore [title=" + title + ", summary=" + summary + ", content=" + content + ", author=" + author
		        + "]";
	}
 
}
/**
 * 为字段添加@JsonIgnore注解,可以忽略该字段的序列化和反序列化。
 * 
 * @throws JsonProcessingException 
 */
@Test
public void jsonIgnore() throws JsonProcessingException {
	ArticleIgnore article = new ArticleIgnore();
	article.setTitle("title");
	article.setSummary("summary");
	article.setContent("content");
	article.setAuthor("author");
	
	ObjectMapper mapper = new ObjectMapper();
	System.out.println(mapper.writeValueAsString(article));
	
	String str = "{\"title\":\"title\",\"summary\":\"summary\",\"content\":\"content\",\"author\":\"author\"}";
	ArticleIgnore newArticle = mapper.readValue(str, ArticleIgnore.class);
	System.out.println(newArticle.toString());
}

执行结果:

{"title":"title","content":"content"}
ArticleIgnore [title=title, summary=null, content=content, author=null]

使用JsonIgnoreProperties注解忽略多个字段

为类添加JsonIgnoreProperties注解,可以忽略指定多个字段的序列化和反序列化。

@JsonIgnoreProperties({ "summary", "author" })
public class ArticleIgnoreProperties {
 
	private String title;
	private String summary;
	private String content;
	private String author;
 
	// 省略getter、setter方法
 
	@Override
	public String toString() {
		return "ArticleIgnoreProperties [title=" + title + ", summary=" + summary + ", content=" + content + ", author="
		        + author + "]";
	}
 
}
/**
 * 为类添加@JsonIgnoreProperties注解,忽略指定字段的序列化和反序列化。
 * 
 * @throws JsonProcessingException 
 */
@Test
public void jsonIgnoreProperties() throws JsonProcessingException {
	ArticleIgnoreProperties article = new ArticleIgnoreProperties();
	article.setTitle("title");
	article.setSummary("summary");
	article.setContent("content");
	article.setAuthor("author");
	
	ObjectMapper mapper = new ObjectMapper();
	System.out.println(mapper.writeValueAsString(article));
	
	String str = "{\"title\":\"title\",\"summary\":\"summary\",\"content\":\"content\",\"author\":\"author\"}";
	ArticleIgnoreProperties newArticle = mapper.readValue(str, ArticleIgnoreProperties.class);
	System.out.println(newArticle.toString());
}

执行结果:

{"title":"title","content":"content"}
ArticleIgnoreProperties [title=title, summary=null, content=content, author=null]

JsonIgnore作用于单个字段,JsonIgnoreProperties作用于类的多个字段,两者都是用来忽略指定的字段。

除此之外,还有另外一个以JsonIgnore开头的注解JsonIgnoreType,用于忽略指定类型(类、接口)的字段。

JsonIgnoreType注解

使用JsonIgnoreType注解忽略指定类型的字段

在指定的类型上,添加@JsonIgnoreType注解,可以忽略该类型的字段进行序列化。

public class AnimalIgnoreType {
 
	private String name;
	private Date date;
	private Address address;
 
	@JsonIgnoreType
	public static class Address {
		private String city;
 
		// 忽略getter、setter方法
 
		@Override
		public String toString() {
			return "Address [city=" + city + "]";
		}
		
	}
 
	// 忽略getter、setter方法
 
	@Override
	public String toString() {
		return "AnimalIgnoreType [name=" + name + ", date=" + date + ", address=" + address + "]";
	}
 
}
/**
 * 如果需要忽略某个具体的类型(类、接口)的序列化,可以使用@JsonIgnoreType注解来实现。
 * 
 * @throws JsonProcessingException
 */
@Test
public void ignoreType() throws JsonProcessingException {
	AnimalIgnoreType animal = new AnimalIgnoreType();
	animal.setName("sam");
	animal.setDate(new Date());
	
	AnimalIgnoreType.Address address = new AnimalIgnoreType.Address();
	address.setCity("gz");
	animal.setAddress(address);
	
	ObjectMapper mapper = new ObjectMapper();
	System.out.println(mapper.writeValueAsString(animal));
	
	String jsonString = "{\"name\":\"sam\",\"date\":1601714443779,\"address\":{\"city\":\"gz\"}}";
	AnimalIgnoreType newAnimal = mapper.readValue(jsonString, AnimalIgnoreType.class);
	System.out.println(newAnimal.toString());
}

执行结果:

{"name":"sam","date":1601726994454}
AnimalIgnoreType [name=sam, date=Sat Oct 03 16:40:43 CST 2020, address=null]

由于Address类型添加了忽略类型的注解,因此在序列化和反序列化时该类型的字段被忽略了。

使用JsonIgnoreType注解动态忽略指定类型的字段

前面使用JsonIgnoreType注解,忽略的类型是固定的。

利用ObjectMapper的addMixIn方法,可以动态的将JsonIgnoreType注解应用于其他数据类型。

public class AnimalIgnoreType {
 
	private String name;
	private Date date;
	private Address address;
 
	public static class Address {
		private String city;
 
		// 省略getter、setter方法
 
		@Override
		public String toString() {
			return "Address [city=" + city + "]";
		}
		
	}
 
	// 省略getter、setter方法
 
	@Override
	public String toString() {
		return "AnimalIgnoreType [name=" + name + ", date=" + date + ", address=" + address + "]";
	}
 
}

首先,定义一个空的类,并添加JsonIgnoreType注解。

@JsonIgnoreType
public class IgnoreType {}

在序列化时,调用ObjectMapper的addMixIn方法,将JsonIgnoreType注解应用于目标类。

下面的例子,会将IgnoreType类的注解,添加到Date和Address上,因此序列化时这两个类对应的字段会被忽略。

/**
 * 调用ObjectMapper的addMixIn方法,将@JsonIgnoreType注解应用于任意目标类.
 * 
 * @throws JsonProcessingException
 */
@Test
public void mixIn() throws JsonProcessingException {
	AnimalIgnoreType animal = new AnimalIgnoreType();
	animal.setName("sam");
	animal.setDate(new Date());
	
	AnimalIgnoreType.Address address = new AnimalIgnoreType.Address();
	address.setCity("gz");
	animal.setAddress(address);
	
	ObjectMapper mapper = new ObjectMapper();
	mapper.addMixIn(Date.class, IgnoreType.class);
	mapper.addMixIn(Address.class, IgnoreType.class);
	System.out.println(mapper.writeValueAsString(animal));
}

执行结果:

{"name":"sam"}

小结

如果需要忽略某个指定的字段,使用JsonIgnore注解是最简单的方式。

如果需要忽略多个字段,有时候可能还会调整,那么使用JsonIgnoreProperties注解将会更加灵活。

有时候,要忽略的是指定数据类型的字段,上面两种方法就不太方便了。Jackson为我们提供了另外一种方式,可以使用JsonIgnoreType注解来忽略某个固定的类型,或者结合ObjectMapper的addMixIn方法来动态忽略某个数据类型的字段。

参考

https://www.baeldung.com/jackson-ignore-properties-on-serialization (opens in a new tab)