知識庫 / JSON / Jackson RSS 訂閱

Jackson – JsonMappingException (序列化異常)

Data,Jackson
HongKong
6
10:04 PM · Dec 05 ,2025

1. 概述

本快速教程將分析沒有獲取器(getters)的實體 marshalling 以及針對 Jackson <em >JsonMappingException</em > 異常的解決方案。

如果您想更深入地瞭解 Jackson 2 可以做什麼的其他酷炫功能,請訪問主 Jackson 教程。

2. 問題

默認情況下,Jackson 2 僅會處理具有以下任何一種屬性的字段:公開的字段,或具有公開的 getter 方法。 如果實體所有字段都設置為私有或包私有,則序列化實體將會失敗

public class MyDtoNoAccessors {
    String stringValue;
    int intValue;
    boolean booleanValue;

    public MyDtoNoAccessors() {
        super();
    }

    // no getters
}
@Test(expected = JsonMappingException.class)
public void givenObjectHasNoAccessors_whenSerializing_thenException() 
  throws JsonParseException, IOException {
    String dtoAsString = new ObjectMapper().writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, notNullValue());
}

完整的異常信息是:

com.fasterxml.jackson.databind.JsonMappingException: 
No serializer found for class dtos.MyDtoNoAccessors 
and no properties discovered to create BeanSerializer 
(to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )

3. 解決方案

顯而易見的方法是為字段添加 getter – 如果該實體在我們控制之下。如果情況並非如此,且無法修改實體的源頭 – 則 Jackson 提供了幾個替代方案。

3.1. 全局自動檢測所有可見字段

一種解決此問題的方案是全局配置 ObjectMapper 以檢測所有字段,無論其可見性如何:

objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

這將允許檢測私有和包私有字段,而無需使用 getter 方法,並且序列化將正常工作

@Test
public void givenObjectHasNoAccessors_whenSerializingWithAllFieldsDetected_thenNoException() 
  throws JsonParseException, IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
    String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, containsString("intValue"));
    assertThat(dtoAsString, containsString("stringValue"));
    assertThat(dtoAsString, containsString("booleanValue"));
}

3.2. 在類級別檢測所有字段

Jackson 2 還提供了一種選項——而不是全局配置,通過使用 @JsonAutoDetect 註解,控制類級別的字段可見性

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class MyDtoNoAccessors { ... }

通過此註釋,序列化現在應該能夠正確地與此特定類一起工作。

@Test
public void givenObjectHasNoAccessorsButHasVisibleFields_whenSerializing_thenNoException() 
  throws JsonParseException, IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, containsString("intValue"));
    assertThat(dtoAsString, containsString("stringValue"));
    assertThat(dtoAsString, containsString("booleanValue"));
}

4. 在 Jackson 中禁用 fail_on_empty_beans

在 Jackson 中,fail_on_empty_beans 功能確定在序列化時,如果對象為空(沒有屬性)是否應拋出異常。 默認情況下,Jackson 在遇到空 Bean 時會拋出異常。

值得注意的是,fail_on_empty_beans 功能默認啓用,因此如果我們想要禁用它,則需要顯式將其設置為 false。 可以通過以下兩種方式來實現,具體取決於我們的特定用例。

4.1. 使用對象映射器配置

我們可以通過直接使用 ObjectMapper 來禁用 fail_on_empty_beans

ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

通過以這種方式配置 ObjectMapper,我們告訴 Jackson 在遇到空 Bean 時,不拋出異常。

4.2. 使用 Spring Boot

在 Spring Boot 中,我們可以通過在 application.properties文件中設置以下屬性來全局禁用 fail_on_empty_beans

spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false

此屬性可設置為應用程序級別,以控制 Jackson 序列化在整個應用程序中的行為。

5. 結論

本文介紹瞭如何繞過 Jackson 默認字段可見性的方法,通過在 ObjectMapper 全局範圍內或在單個類上配置自定義可見性來實現。Jackson 允許更進一步的自定義,通過提供選項來控制映射器如何看待獲取器、設置器或具有特定可見性的字段。

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

發佈 評論

Some HTML is okay.