1. 程式人生 > 實用技巧 >基於jackson動態序列化指定欄位

基於jackson動態序列化指定欄位

一、前言

把物件序列化為json字串輸出的庫很多,本文我們來看如何基於jackson動態控制哪些屬性需要進行序列化。

二、序列化輸出方式

對應使用Jackson,需要我們在pom檔案中引入下面依賴:

<dependency&gt;
    <groupId&gt;com.fasterxml.jackson.core</groupId&gt;
    <artifactId&gt;jackson-databind</artifactId&gt;
    <version&gt;2.11.1</version&gt;
</dependency&gt;

首先簡單看下如何使用:

  @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註解,如果沒有指定過濾器,則執行時會報錯,那麼如何讓一個類即可以支援動態過濾,又在沒指定過濾器的情況下正常執行那?其實很簡單,我們可以自定義註解並註冊…