知識庫 / Spring / Spring Boot RSS 訂閱

使用 camel-jackson 解析 JSON 數組

Jackson,Spring Boot
HongKong
6
09:51 PM · Dec 05 ,2025

1. 概述

Apache Camel 是一個強大的開源集成框架,它實現了許多已知的企業集成模式。

通常在通過 Camel 進行消息路由時,我們希望使用許多支持的插件式 數據格式。 鑑於 JSON 在許多現代 API 和數據服務中很受歡迎,因此它成為一種常見的選擇。

在本教程中,我們將探討使用 camel-jackson 組件將 JSON 數組解析為 Java 對象列表的幾種方法。

2. 依賴項

首先,我們將 camel-jackson-starter 依賴項添加到我們的 pom.xml 中:

<dependency>
    <groupId>org.apache.camel.springboot</groupId>
    <artifactId>camel-jackson-starter</artifactId>
    <version>3.21.0</version>
</dependency>

然後,我們還會添加 camel-test-spring-junit5 依賴項,專門用於我們的單元測試:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-test-spring-junit5</artifactId>
    <version>3.21.0</version>
    <scope>test</scope>
</dependency>

3. 結果領域類

在本文教程中,我們將使用幾個輕量級的POJO對象來建模我們的結果領域。

讓我們定義一個具有 idname 屬性來表示水果的類:

public class Fruit {

    private String name;
    private int id;

    // standard getter and setters
}

接下來,我們將定義一個容器來存儲一個 Fruit 對象列表:

public class FruitList {

    private List<Fruit> fruits;

    public List<Fruit> getFruits() {
        return fruits;
    }

    public void setFruits(List<Fruit> fruits) {
        this.fruits = fruits;
    }
}

在接下來的幾個部分中,我們將看到如何將表示水果列表的 JSON 字符串反序列化為這些領域類最終,我們所要達到的目標是創建一個類型為 List<Fruit>的變量,以便我們能夠對其進行操作.

4. 解析 JSON 中的 FruitList 列表

在第一個示例中,我們將使用 JSON 格式表示一個簡單的水果列表:

{
    "fruits": [
        {
            "id": 100,
            "name": "Banana"
        },
        {
            "id": 101,
            "name": "Apple"
        }
    ]
}

最重要的是,我們應該強調的是,這個JSON代表一個對象,其中包含一個名為fruits的屬性,該屬性包含我們的數組。

現在,讓我們設置Apache Camel路由以執行反序列化:

@Bean
RoutesBuilder route() {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            from("direct:jsonInput").unmarshal(new JacksonDataFormat(FruitList.class))
              .to("mock:marshalledObject");
        }
    };
}

在此示例中,我們使用名為 jsonInput 的直接端點。然後,我們調用 unmarshal 方法,該方法將我們接收到的 Camel 交換的消息主體序列化為指定的數據格式。

我們使用 JacksonDataFormat 類,自定義的 unmarshal 類型為FruitList. 這本質上是圍繞 Jackon ObjectMapper 的一個簡單包裝器,允許我們進行 JSON 序列化和反序列化。

最後,我們將 unmarshal 方法的結果發送到名為 marshalledObject 的模擬端點。 如你所見,這就是我們測試路由是否正確的方法。

考慮到這一點,讓我們編寫第一個單元測試:

@CamelSpringBootTest
@SpringBootTest
public class FruitListJacksonUnmarshalUnitTest {

    @Autowired
    private ProducerTemplate template;

    @EndpointInject("mock:marshalledObject")
    private MockEndpoint mock;

    @Test
    public void givenJsonFruitList_whenUnmarshalled_thenSuccess() throws Exception {
        mock.setExpectedMessageCount(1);
        mock.message(0).body().isInstanceOf(FruitList.class);

        String json = readJsonFromFile("/json/fruit-list.json");
        template.sendBody("direct:jsonInput", json);
        mock.assertIsSatisfied();

        FruitList fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(FruitList.class);
        assertNotNull("Fruit lists should not be null", fruitList);

        List<Fruit> fruits = fruitList.getFruits();
        assertEquals("There should be two fruits", 2, fruits.size());

        Fruit fruit = fruits.get(0);
        assertEquals("Fruit name", "Banana", fruit.getName());
        assertEquals("Fruit id", 100, fruit.getId());

        fruit = fruits.get(1);
        assertEquals("Fruit name", "Apple", fruit.getName());
        assertEquals("Fruit id", 101, fruit.getId());
    }
}

讓我們逐步瞭解我們的測試的關鍵部分,以瞭解發生了什麼:

  1. 首先,我們通過添加 @CamelSpringBootTest 註解來開始,這是一個用於測試 Camel 與 Spring Boot 的有用註解。
  2. 然後,我們使用 @EndpointInject 註解注入 MockEndpoint。此註解允許我們在不手動從 Camel 上下文中查找它們的情況下設置模擬端點。在這裏,我們將 mock:marshalledObject 設置為 Camel 端點的 URI。它指向一個名為 marshalledObjectmock 端點。
  3. 之後,我們設置測試期望。我們的 mock 端點應接收一條消息,且消息類型應為 FruitList
  4. 現在,我們準備將 JSON 輸入文件作為 String 發送到我們之前定義的 direct 端點。我們使用 ProducerTemplate 類將消息發送到端點。
  5. 在檢查我們的 mock 期望是否已滿足後,我們可以檢索 FruitList 並檢查其內容是否符合預期。

此測試確認我們的路由正常工作,並且 JSON 按照預期進行反序列化。太棒了!

5. 解析 JSON 水果 數組

另一方面,我們可能不想使用容器對象來存儲我們的 水果 對象。我們可以修改 JSON 以直接存儲水果數組:

[
    {
        "id": 100,
        "name": "Banana"
    },
    {
        "id": 101,
        "name": "Apple"
    }
]

現在,我們的路由幾乎完全相同,但我們將其配置為專門處理 JSON 數組:

@Bean
RoutesBuilder route() {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            from("direct:jsonInput").unmarshal(new ListJacksonDataFormat(Fruit.class))
              .to("mock:marshalledObject");
        }
    };
}

如我們所見,與我們之前的示例唯一的區別在於我們使用了 ListJacksonDataFormat 類,並指定了自定義的解映射類型為 Fruit這是一種 Jackson 數據格式類型,我們可以使用它來處理列表

同樣,我們的單元測試非常相似:

@Test
public void givenJsonFruitArray_whenUnmarshalled_thenSuccess() throws Exception {
    mock.setExpectedMessageCount(1);
    mock.message(0).body().isInstanceOf(List.class);

    String json = readJsonFromFile("/json/fruit-array.json");
    template.sendBody("direct:jsonInput", json);
    mock.assertIsSatisfied();

    @SuppressWarnings("unchecked")
    List<Fruit> fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(List.class);
    assertNotNull("Fruit lists should not be null", fruitList);

    assertEquals("There should be two fruits", 2, fruitList.size());

    Fruit fruit = fruitList.get(0);
    assertEquals("Fruit name", "Banana", fruit.getName());
    assertEquals("Fruit id", 100, fruit.getId());

    fruit = fruitList.get(1);
    assertEquals("Fruit name", "Apple", fruit.getName());
    assertEquals("Fruit id", 101, fruit.getId());
}

然而,與之前章節中看到的測試存在兩個微妙的差異:

  • 我們首先設置mock期望,使其包含一個帶有 List.class 的主體。
  • 當我們以 List.class 的形式檢索消息主體時,我們會收到關於類型安全的標準警告——因此使用了 @SuppressWarnings(“unchecked”)

6. 結論

在本文中,我們看到了兩種簡單的 JSON 數組反序列化方法,即使用 camel message routing 和 camel-jackson 組件。 這兩種方法的主要區別在於,JacksonDataFormat 會將數據反序列化為對象類型,而 ListJacksonDataFormat 則會將數據反序列化為列表類型。

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

發佈 評論

Some HTML is okay.