public class Book implements Serializable {
private String title;
private int year;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public int getYear() {
return this.year;
}
public void setYear(int year) {
this.year = year;
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
b.setYear(2017);
String json = new ObjectMapper().writeValueAsString(b);
System.out.println(json); // {"title":"Jackson","year":2017}
Map<String, String> m = new ObjectMapper().readValue(json, Map.class);
System.out.println(m); // {title=Jackson, year=2017}
}
}
但聽說它有非常多特別的 Annotation。@JsonIgnoreProperties & @JsonIgnore
使用 Jackson 最常見的需求就是,不要輸出某些欄位,可能原因有:安全考量(密碼欄位)、資料量(大物件或者 List / Map)、遞迴參考(會當掉?)以及 Lazy 屬性(Hibernate 未初始化的關聯屬性)。有四種設定方式。
Class Level - @JsonIgnoreProperties
@JsonIgnoreProperties({
"contractAmt"
})
public class Book implements Serializable {
private String title;
private int contractAmt;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public int getContractAmt() {
return this.contractAmt;
}
public void setContractAmt(int contractAmt) {
this.contractAmt = contractAmt;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
b.setContractAmt(1099);
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"title":"Jackson"}
}
}
Field Level - @JsonIgnore
public class Book8 implements Serializable {
private String title;
private int contractAmt;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
@JsonIgnore
public int getContractAmt() {
return this.contractAmt;
}
public void setContractAmt(int contractAmt) {
this.contractAmt = contractAmt;
}
public static void main(String[] args) throws IOException {
Book8 b = new Book8();
b.setTitle("Jackson");
b.setContractAmt(1099);
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"title":"Jackson"}
}
}
特定 Java Type - @JsonIgnoreType
public class Book implements Serializable {
private String title;
private Address address;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Address getAddress() {
return this.address;
}
public void setAddress(Address address) {
this.address = address;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"title":"Jackson"}
}
}
@JsonIgnoreType
class Address {
}
但是當你「摸不到」別人家的 Java type 時,可以改用 Mixin(混搭)的方式 - addMixIn。public class Book implements Serializable {
private String title;
private Date signedDate;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getSignedDate() {
return this.signedDate;
}
public void setSignedDate(Date signedDate) {
this.signedDate = signedDate;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
b.setSignedDate(new Date(117, 11, 31));
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(b));
// {"title":"Jackson","signedDate":1514649600000}
mapper = new ObjectMapper();
mapper.addMixIn(Date.class, SqlDateMixin.class);
System.out.println(mapper.writeValueAsString(b));
// {"title":"Jackson"}
}
}
@JsonIgnoreType
class SqlDateMixin {
}
Filter - @JsonFilter
@JsonFilter("secret")
public class Book implements Serializable {
private String title;
private Date signedDate;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getSignedDate() {
return this.signedDate;
}
public void setSignedDate(Date signedDate) {
this.signedDate = signedDate;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
b.setSignedDate(new Date(117, 11, 31));
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider filters = new SimpleFilterProvider();
filters.addFilter("secret", SimpleBeanPropertyFilter.serializeAllExcept("signedDate"));
mapper.setFilterProvider(filters);
System.out.println(mapper.writeValueAsString(b));
// {"title":"Jackson"}
}
}
@JsonProperty & @JsonGetter
預設狀況下,JSON 的屬性名稱是使用 Java Bean 的 property name,@JsonProperty 可以在不修改 Java Bean 的情況下自訂JSON 的屬性名稱,也可以用更為通用的 @JsonGetter 達成一樣的目的。public class Book implements Serializable {
private String title;
private int year;
@JsonProperty("name")
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public int getYear() {
return this.year;
}
public void setYear(int year) {
this.year = year;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
b.setYear(2017);
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"year":2017,"name":"Jackson"}
}
}
Include.NON_NULL
不要輸出 null 值的欄位,有三個設定 level:global、class 與 field 。Global Level - setSerializationInclusion(Include.NON_NULL)
public class Book implements Serializable {
private String title;
private String author;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return this.author;
}
public void setAuthor(String author) {
this.author = author;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
// b.setAuthor("MJ");
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"title":"Jackson","author":null}
System.out.println(new ObjectMapper().setSerializationInclusion(Include.NON_NULL).writeValueAsString(b));
// {"title":"Jackson"}
}
}
Class Level - @JsonInclude(Include.NON_NULL)
@JsonInclude(Include.NON_NULL)
public class Book implements Serializable {
private String title;
private String author;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return this.author;
}
public void setAuthor(String author) {
this.author = author;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
// b.setAuthor("MJ");
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"title":"Jackson"}
}
}
Field Level - @JsonInclude(Include.NON_NULL)
public class Book implements Serializable {
private String title;
private String author;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
@JsonInclude(Include.NON_NULL)
public String getAuthor() {
return this.author;
}
public void setAuthor(String author) {
this.author = author;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
// b.setAuthor("MJ");
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"title":"Jackson"}
}
}
@JsonInclude 雖然名為 include,但實際上卻是用來 exclude 的,Include 除了 NON_NULL,還有 ALWAYS(預設)、NON_ABSENT、NON_EMPTY 與 NON_DEFAULT。@JsonAnyGetter
預設狀況下,Map 物件會轉成 JSON 物件。public class Book implements Serializable {
private String title;
private Map<String, String> histories = new HashMap<String, String>();
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Map<String, String> getHistories() {
return this.histories;
}
public void setHistories(Map<String, String> histories) {
this.histories = histories;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
b.getHistories().put("rev1", "20170101...");
b.getHistories().put("rev2", "20170201...");
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"title":"Jackson","histories":{"rev2":"20170201...","rev1":"20170101..."}}
}
}
@JsonAnyGetter 可以將 Map 裡的名值對抽出來,有點 flatten 的味道。public class Book implements Serializable {
private String title;
private Map<String, String> histories = new HashMap<String, String>();
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
@JsonAnyGetter
public Map<String, String> getHistories() {
return this.histories;
}
public void setHistories(Map<String, String> histories) {
this.histories = histories;
}
public static void main(String[] args) throws IOException {
Book b = new Book();
b.setTitle("Jackson");
b.getHistories().put("rev1", "20170101...");
b.getHistories().put("rev2", "20170201...");
System.out.println(new ObjectMapper().writeValueAsString(b));
// {"title":"Jackson","rev2":"20170201...","rev1":"20170101..."}
}
}
@JsonRawValue
直接輸出原始內容,不去處理 JSON 專用的雙引號,可以用來輸出手打的 JSON 字串。public class Book13 implements Serializable {
private String title;
private String json;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
@JsonRawValue
public String getJson() {
return this.json;
}
public void setJson(String json) {
this.json = json;
}
public static void main(String[] args) throws IOException {
Book13 b = new Book13();
b.setTitle("Jackson");
b.setJson("{\"title\":\"Jackson\"}");
System.out.println(new ObjectMapper().writeValueAsString(b));
// 一般欄位 - {"title":"Jackson","json":"{\"title\":\"Jackson\"}"}
// @JsonRawValue - {"title":"Jackson","json":{"title":"Jackson"}}
}
}
@JsonValue
效果類似 toString(),用該 method 回傳的值表示該 instance,適合用於enum。public class Book14 implements Serializable {
private String title;
private BookType type;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public BookType getType() {
return this.type;
}
public void setType(BookType type) {
this.type = type;
}
public static void main(String[] args) throws IOException {
Book14 b = new Book14();
b.setTitle("Jackson");
b.setType(BookType.Computer);
System.out.println(new ObjectMapper().writeValueAsString(b));
// 一般欄位 - {"title":"Jackson","type":"Computer"}
// @JsonValue - {"title":"Jackson","type":"COMPUTER"}
}
}
enum BookType {
Computer("COMPUTER"), Science("SCIENCE");
private String name;
BookType(String name) {
this.name = name;
}
@JsonValue
public String getName() {
return name;
}
}
@JsonRootName
Jackson 可以透過 SerializationFeature.WRAP_ROOT_VALUE 將自身也輸出,但自身預設為 class name,可以用 @JsonRootName 自訂自身名稱。@JsonRootName("book")
public class Book15 implements Serializable {
private String title;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public static void main(String[] args) throws IOException {
Book15 b = new Book15();
b.setTitle("Jackson");
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
System.out.println(mapper.writeValueAsString(b));
// 一般欄位 - {"Book15":{"title":"Jackson"}}
// @JsonRootName - {"book":{"title":"Jackson"}}
}
}
@JsonSerialize
自訂物件輸出的內容。public class Book16 implements Serializable {
private String title;
private Date publishDate;
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getPublishDate() {
return this.publishDate;
}
@JsonSerialize(using = DateSerialize.class)
public Date getPublishDateFormatted() {
return this.publishDate;
}
public void setPublishDate(Date publishDate) {
this.publishDate = publishDate;
}
public static void main(String[] args) throws IOException {
Book16 b = new Book16();
b.setTitle("Jackson");
b.setPublishDate(new Date());
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(b));
// {"title":"Jackson","publishDate":1514390929846,"publishDateFormatted":2017-12-28 00:08:49}
}
}
class DateSerialize extends JsonSerializer<Date> {
private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeRawValue(df.format(value));
}
}
------
---
沒有留言:
張貼留言