天天看點

如何基于jackson動态序列化指定字段

作者:技術聯盟總壇
如何基于jackson動态序列化指定字段

一、前言

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

二、序列化輸出方式

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

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.1</version>
</dependency>           

首先簡單看下如何使用:

@Data
    @JsonFilter("car")
    static class Car {
        private String brand;
        private long price;
        private int load;
        private long id;
    }


    @Data
    @JsonFilter("house")
    static class House {
        private String title;
        private long price;
        private long id;
    }


    @Data
    @JsonFilter("person")
    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,就可以做這個事件。

@Data
    @JsonFilter("car")
    static class Car {
     ...
    }


    @Data
    @JsonFilter("house")
    static class House {
    ...
    }


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

繼續閱讀