基於jackson動態序列化指定欄位
一、前言
把物件序列化為json字串輸出的庫很多,本文我們來看如何基於jackson動態控制哪些屬性需要進行序列化。
二、序列化輸出方式
對應使用Jackson,需要我們在pom檔案中引入下面依賴:
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.11.1</version> </dependency>
首先簡單看下如何使用:
@Data static class Car { private String brand; private long price; private int load; private long id; } @Data static class House { private String title; private long price; private long id; } @Data static class Person { private Car car; private House house; private long weight; private long id; private String name; } public static Person makePerson() { Person person = new Person(); person.setName("加多"); person.setWeight(150); person.setId(8888); House house = new House(); house.setId(234); house.setTitle("杭州院子"); house.setPrice(10000000); person.setHouse(house); Car car = new Car(); car.setBrand("瑪莎拉蒂"); car.setId(123L); car.setLoad(3); car.setPrice(1000000); person.setCar(car); return person; } public static void main(String[] arg) throws JsonProcessingException { //1.造人 Person person = makePerson(); //2.序列化為json字串並輸出 ObjectMapper objectMapper = new ObjectMapper(); System.out.println(objectMapper.writeValueAsString(person)); }
如上程式碼1,建立了一個Person類,程式碼2建立ObjectMapper,並且呼叫其writeValueAsString方法,把Person物件序列化為字串,然後列印輸出,結果為:
{ "car":{ "brand":"瑪莎拉蒂", "price":1000000, "load":3, "id":123 }, "house":{ "title":"杭州院子", "price":10000000, "id":234 }, "weight":150, "id":8888, "name":"加多" }
如上Person中所有屬性,包含其中Car中所有屬性,House的所屬性都輸出了。
如果我們不想序列化某個屬性,比如不想序列化Person中的Car中的price屬性,則我們只需要在Car類屬性上加註解:@JsonIgnore
:
@Data static class Car { private String brand; @JsonIgnore private long price; ... }
同理如果不想要序列化Person中的car屬性,在其上新增@JsonIgnore
註解即可。
對應上面情況,我們只能靜態的使用@JsonIgnore
註解來過濾不需要序列化的屬性,那麼有沒有辦法在執行時進行動態過濾不需要過濾的屬性那?其實註解@JsonFilter
,就可以做這個事件。
@JsonFilter("car") static class Car { ... } @JsonFilter("house") static class House { ... } @JsonFilter("person") static class Person { ... }
如上首先在所有類上加上對應的註解,然後通過下面程式碼新增過濾器:
public static void main(String[] arg) throws JsonProcessingException { //1.造人 Person person = makePerson(); //2.序列化為json字串並輸出 ObjectMapper objectMapper = new ObjectMapper(); //2.1建立過濾器 SimpleFilterProvider filterProvider = new SimpleFilterProvider(); //2.1.1Person類的屬性過濾器(只序列化car,house,name欄位) filterProvider.addFilter("person", SimpleBeanPropertyFilter.filterOutAllExcept(Sets.newHashSet("car", "house", "name"))); //2.1.2House類的屬性過濾器(只序列化title,price欄位) filterProvider.addFilter("house", SimpleBeanPropertyFilter.filterOutAllExcept(Sets.newHashSet("title", "price"))); //2.1.3Car類的屬性過濾器(只序列化brand欄位) filterProvider.addFilter("car", SimpleBeanPropertyFilter.filterOutAllExcept(Sets.newHashSet("brand"))); //2.2設定過濾器,並執行序列化 objectMapper.setFilterProvider(filterProvider); System.out.println(objectMapper.writeValueAsString(person)); }
如上程式碼通過2.1.1-2.1.3為Person,House,Car添加了屬性過濾器,只序列化指定的欄位,然後程式碼2.2把過濾器設定到ObjectMapper物件裡面,最後執行序列化,執行上面程式碼,輸出如下:
{ "car":{ "brand":"瑪莎拉蒂" }, "house":{ "title":"杭州院子", "price":10000000 }, "name":"加多" }
可知序列化時,只序列化了我們指定的欄位。上面程式碼只是一個例項,在執行時,我們可以根據需要動態設定過濾器,來起到動態序列化指定欄位的功能。
三、總結
本文我們談論瞭如何使用@JsonFilter
進行動態指定需要序列化欄位的功能。需要注意的是一旦一個類上加了@JsonFilter
註解,如果沒有指定過濾器,則執行時會報錯,那麼如何讓一個類即可以支援動態過濾,又在沒指定過濾器的情況下正常執行那?其實很簡單,我們可以自定義註解並註冊…