JSON類庫Jackson優雅序列化Java枚舉類

1. 前言

Java開發中我們為了避免過多的魔法值,使用枚舉類來封裝一些靜態的狀態代碼。但是在將這些枚舉的意思正確而全面的返回給前端卻並不是那麼順利,我們通常會使用Jackson類庫序列化對象為JSON,今天就來講一個關於使用Jackson序列化枚舉的通用性技巧。

2. 通用枚舉範式

為了便於統一處理和規範統一的風格,建議指定一個統一的抽象接口,例如:

/**
 * The interface Enumerator.
 */
public interface Enumerator {
    /**
     * Code integer.
     *
     * @return the integer
     */
    Integer code();

    /**
     * Description string.
     *
     * @return the string
     */
    String description();
}

我們來寫一個實現來標識性別:

public enum GenderEnum implements Enumerator {
   
    UNKNOWN(0, "未知"),

    MALE(1, "男"),

    FEMALE(2, "女");


    private final Integer code;
    private final String description;

    GenderEnum(Integer code, String description) {
        this.code = code;
        this.description = description;
    }


    @Override
    public Integer code() {
        return code;
    }

    @Override
    public String description() {
        return description;
    }
}

3. 序列化枚舉

如果我們直接使用Jackson對枚舉進行序列化,將只能簡單的輸出枚舉的String名稱:

    @Resource
    private ObjectMapper objectMapper;

    @Test
    void enumTest() {
        try {
            String s = objectMapper.writeValueAsString(GenderEnum.MALE);
            // 輸出字符串 MALE
            System.out.println(s);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

我們期望將GenderEnum.MALE 序列化為 {"code":1,"description":"男"} 。我們可以向ObjectMapper定製化一個Module來實現這種個性化需求:

         // 聲明一個簡單Module 對象
         SimpleModule module = new SimpleModule();
           // 給Module 添加一個序列化器
            module.addSerializer(Enumerator.class, new JsonSerializer<Enumerator>() {
                @Override
                public void serialize(Enumerator value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                   // 開始寫入對象
                    gen.writeStartObject();
                    // 分別指定 k v   code   description 
                    gen.writeNumberField("code",value.code());
                    gen.writeStringField("description",value.description());
                    // 顯式結束操作
                    gen.writeEndObject();
                }
            });

        // 註冊 Module
        objectMapper.registerModule(module);

然後再次執行就會獲取我們期望的結果。然而這並不算合理。

4. Spring Boot 中自動全局配置

Spring Boot應用中我們希望能全局配置。Spring Boot的自動配置為我們提供了一個個性化定製ObjectMapper的可能性,你只需要聲明一個Jackson2ObjectMapperBuilderCustomizer並注入Spring IoC:

@Bean
public Jackson2ObjectMapperBuilderCustomizer enumCustomizer(){
    return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.serializerByType(Enumerator.class, new JsonSerializer<Enumerator>() {
        @Override
        public void serialize(Enumerator value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                    gen.writeStartObject();
                    gen.writeNumberField("code",value.code());
                    gen.writeStringField("description",value.description());
                    gen.writeEndObject();


        }
    });
}

這樣就實現了全局配置。

5. 總結

這裏我們介紹了如何定製Jackson庫以達到對枚舉進行更加友好的序列化的目的。其實不單單枚舉,你也可以實現其它序列化,反序列化,時間輸出格式的定製。這些特性留給你自己挖掘。多多關注:碼農小胖哥 獲取更多開發技巧。

關注公眾號:Felordcn 獲取更多資訊

個人博客:https://felord.cn

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

台北網頁設計公司這麼多該如何選擇?

※智慧手機時代的來臨,RWD網頁設計為架站首選

※評比南投搬家公司費用收費行情懶人包大公開

※幫你省時又省力,新北清潔一流服務好口碑

※回頭車貨運收費標準