知識庫 / JSON / Jackson RSS 訂閱

將布爾值序列化為整數與 Jackson

Jackson
HongKong
10
09:50 PM · Dec 05 ,2025

1. 簡介

Jackson 庫在 Java 世界中,尤其是在處理 JSON 方面,被廣泛認為是事實上的標準。儘管 Jackson 具有明確定義的默認設置,但要將 Boolean 值映射到 Integer 時,我們仍然需要進行手動配置。

當然,一些開發者會思考如何以最佳方式和最少的工作量來實現這一點。

在本文中,我們將解釋如何將 Boolean 值序列化為 Integer 值(以及數字字符串)以及反過來,在 Jackson 中實現。

2. 序列化

首先,我們將探討序列化這一部分。為了測試布爾值整數序列化,我們先定義我們的模型,遊戲

public class Game {

    private Long id;
    private String name;
    private Boolean paused;
    private Boolean over;

    // constructors, getters and setters
}

通常情況下,Game對象的默認序列化將使用 Jackson 的 ObjectMapper

ObjectMapper mapper = new ObjectMapper();
Game game = new Game(1L, "My Game");
game.setPaused(true);
game.setOver(false);
String json = mapper.writeValueAsString(game);

unsurprisingly, 對於 布爾值 字段的輸出將是默認值——truefalse

{"id":1, "name":"My Game", "paused":true, "over":false}

然而,我們最終希望從我們的 Game 對象中獲得以下 JSON 輸出:

{"id":1, "name":"My Game", "paused":1, "over":0}

2.1. 字段級別配置

將數據序列化為 Integer 的一種簡單方法是,對我們的 Boolean 字段進行註解,並設置 Shape.NUMBER

@JsonFormat(shape = Shape.NUMBER)
private Boolean paused;

@JsonFormat(shape = Shape.NUMBER)
private Boolean over;

然後,我們來在測試方法中嘗試序列化:

ObjectMapper mapper = new ObjectMapper();
Game game = new Game(1L, "My Game");
game.setPaused(true);
game.setOver(false);
String json = mapper.writeValueAsString(game);

assertThat(json)
  .isEqualTo("{\"id\":1,\"name\":\"My Game\",\"paused\":1,\"over\":0}");

正如我們從JSON輸出中看到的,我們的布爾值字段——暫停結束——轉換成了數字10。由於它們沒有被引號包圍,因此可以清楚地看出這些值是整數格式。

2.2 全局配置

有時,對每個字段進行註釋可能不切實際。例如,根據要求,我們可能需要全局配置我們的 BooleanInteger 序列化。

幸運的是,Jackson 允許我們通過在 ObjectMapper 中覆蓋默認值來全局配置 @JsonFormat

ObjectMapper mapper = new ObjectMapper();
mapper.configOverride(Boolean.class)
  .setFormat(JsonFormat.Value.forShape(Shape.NUMBER));

Game game = new Game(1L, "My Game");
game.setPaused(true);
game.setOver(false);
String json = mapper.writeValueAsString(game);

assertThat(json)
  .isEqualTo("{\"id\":1,\"name\":\"My Game\",\"paused\":1,\"over\":0}");

3. 反序列化

同樣,在反序列化 JSON 字符串到模型時,我們可能也需要從數字中獲取 布爾值

幸運的是,Jackson 可以解析數字——僅限於 10 —— 為 布爾值。因此,我們不需要使用 @JsonFormat 註解或任何其他配置。

因此,無需配置,讓我們通過另一個測試方法來觀察這種行為:

ObjectMapper mapper = new ObjectMapper();
String json = "{\"id\":1,\"name\":\"My Game\",\"paused\":1,\"over\":0}";
Game game = mapper.readValue(json, Game.class);

assertThat(game.isPaused()).isEqualTo(true);
assertThat(game.isOver()).isEqualTo(false);

因此,Jackson 默認支持 IntegerBoolean 的序列化/反序列化。

4. 使用數字字符串代替整數

另一個使用場景是使用數字字符串——“1”“0”——代替整數。在這種情況下,將 Boolean 值序列化為數字字符串或反序列化為 Boolean 值需要付出更多的努力。

4.1. 將值序列化為數字字符串

為了將 Boolean 值序列化為數字字符串等效值,我們需要定義一個自定義序列化器。

因此,讓我們通過擴展 Jackson 的 JsonSerializer 創建我們的 NumericBooleanSerializer

public class NumericBooleanSerializer extends JsonSerializer<Boolean> {

    @Override
    public void serialize(Boolean value, JsonGenerator gen, SerializerProvider serializers)
      throws IOException {
        gen.writeString(value ? "1" : "0");
    }
}

順便説明的是,通常情況下,布爾型可以為null。但是,Jackson內部處理了這種情況,並且在字段為null時,不會考慮我們的自定義序列化器。因此,這裏我們可以放心。

接下來,我們將註冊我們的自定義序列化器,以便Jackson能夠識別並使用它。

如果我們需要這種行為僅限於少量字段,我們可以使用字段級別的配置,通過@JsonSerialize註解來實現。

相應地,讓我們為pausedover這兩個Boolean字段進行標註:

@JsonSerialize(using = NumericBooleanSerializer.class)
private Boolean paused;

@JsonSerialize(using = NumericBooleanSerializer.class)
private Boolean over;

然後,同樣地,我們也在測試方法中嘗試序列化:

ObjectMapper mapper = new ObjectMapper();
Game game = new Game(1L, "My Game");
game.setPaused(true);
game.setOver(false);
String json = mapper.writeValueAsString(game);

assertThat(json)
  .isEqualTo("{\"id\":1,\"name\":\"My Game\",\"paused\":\"1\",\"over\":\"0\"}");

儘管測試方法實現與之前的版本幾乎相同,但我們應該注意圍繞數字值的引號:“paused”:”1″, “over”:”0″。 顯然,這些值實際上是包含數字內容的字符串。

最後,如果我們需要在任何地方執行此自定義序列化,Jackson 支持通過向 ObjectMapper 添加 Jackson 模塊來全局配置序列化器

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Boolean.class, new NumericBooleanSerializer());
mapper.registerModule(module);

Game game = new Game(1L, "My Game");
game.setPaused(true);
game.setOver(false);
String json = mapper.writeValueAsString(game);

assertThat(json)
  .isEqualTo("{\"id\":1,\"name\":\"My Game\",\"paused\":\"1\",\"over\":\"0\"}");

因此,Jackson 會將所有 Boolean 類型字段序列化為數字字符串,只要我們使用相同的 ObjectMapper 實例。

4.2. 從數值字符串反序列化

類似於序列化,本節我們將定義一個自定義的反序列化器,將數值字符串解析為 Boolean 值。

讓我們通過擴展 JsonDeserializer 類來創建我們的類 NumericBooleanDeserializer

public class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {

    @Override
    public Boolean deserialize(JsonParser p, DeserializationContext ctxt)
      throws IOException {
        if ("1".equals(p.getText())) {
            return Boolean.TRUE;
        }
        if ("0".equals(p.getText())) {
            return Boolean.FALSE;
        }
        return null;
    }

}

接下來,我們再次標註我們的 布爾值字段,但這次使用 @JsonDeserialize

@JsonSerialize(using = NumericBooleanSerializer.class)
@JsonDeserialize(using = NumericBooleanDeserializer.class)
private Boolean paused;

@JsonSerialize(using = NumericBooleanSerializer.class)
@JsonDeserialize(using = NumericBooleanDeserializer.class)
private Boolean over;

那麼,讓我們編寫另一個測試方法,以查看 NumericBooleanDeserializer 的實際效果:

ObjectMapper mapper = new ObjectMapper();
String json = "{\"id\":1,\"name\":\"My Game\",\"paused\":\"1\",\"over\":\"0\"}";
Game game = mapper.readValue(json, Game.class);

assertThat(game.isPaused()).isEqualTo(true);
assertThat(game.isOver()).isEqualTo(false);

當然,以下是翻譯後的內容:

或者,還可以通過 Jackson 模塊以全局配置的方式使用我們的自定義反序列器。

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Boolean.class, new NumericBooleanDeserializer());
mapper.registerModule(module);

String json = "{\"id\":1,\"name\":\"My Game\",\"paused\":\"1\",\"over\":\"0\"}";
Game game = mapper.readValue(json, Game.class);

assertThat(game.isPaused()).isEqualTo(true);
assertThat(game.isOver()).isEqualTo(false);

5. 結論

在本文中,我們描述瞭如何將布爾值序列化為整數和數字字符串,以及如何將它們反序列化回原始值。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.