使用camel-jackson解組JSON數組
1.概述
Apache Camel是一個功能強大的開源集成框架,實現了許多已知的企業集成模式。
通常,在使用Camel處理消息路由時,我們將要使用許多受支持的可插拔數據格式之一。鑑於JSON在大多數現代API和數據服務中都很流行,因此它成為顯而易見的選擇。
在本教程中,我們將介紹使用camel-jackson
組件將JSON數組編組為Java對象列表的幾種方法。
2.依賴關係
首先,讓我們將camel-jackson
依賴項添加到我們的pom.xml
:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
<version>3.6.0</version>
</dependency>
然後,我們還將添加專門用於單元測試的camel-test
依賴項,Maven Central也可以提供它:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test</artifactId>
<version>3.6.0</version>
</dependency>
3.水果領域類
在整個教程中,我們將使用幾個簡單的POJO對象來建模我們的水果領域。
讓我們繼續定義一個帶有ID和名稱的類,以表示水果:
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,
的屬性fruits,
該屬性包含我們的array 。
現在,讓我們設置我們的Apache Camel路由來執行反序列化:
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:jsonInput")
.unmarshal(new JacksonDataFormat(FruitList.class))
.to("mock:marshalledObject");
}
};
}
在此示例中,我們使用名稱為jsonInput
direct
端點。接下來,我們調用unmarshal
方法,該方法使用指定的數據格式對Camel交換上的消息正文進行解組。
我們正在將JacksonDataFormat
類與自定義解組類型的**FruitList** .
從本質上講,這是一個圍繞Jackon ObjectMapper
的簡單包裝器,它使我們能夠往返於JSON。
最後,我們將unmarshal
方法的結果發送到名為marshalledObject
的mock
端點。正如我們將要看到的,這就是我們將測試路線以查看其是否正常運行的方式。
考慮到這一點,讓我們繼續編寫我們的第一個單元測試:
public class FruitListJacksonUnmarshalUnitTest extends CamelTestSupport {
@Test
public void givenJsonFruitList_whenUnmarshalled_thenSuccess() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:marshalledObject");
mock.expectedMessageCount(1);
mock.message(0).body().isInstanceOf(FruitList.class);
String json = readJsonFromFile("/json/fruit-list.json");
template.sendBody("direct:jsonInput", json);
assertMockEndpointsSatisfied();
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());
}
}
讓我們遍歷測試的關鍵部分以了解發生了什麼:
- 首先,我們首先擴展
CamelTestSupport
類-一個有用的測試實用程序基類 - 然後,我們建立了測試期望。我們的
mock
變量應該只有一條消息,消息類型應該是FruitList
- 現在我們準備將JSON輸入文件作為
String
發送到我們先前定義的direct
端點 - 檢查我們的模擬期望是否滿足後,我們可以自由檢索
FruitList
並檢查其內容是否符合預期
此測試確認我們的路由正常運行,並且按預期對JSON進行了編組。驚人的!
5.解組JSON Fruit
數組
另一方面,我們要避免使用容器對象來保存我們的Fruit
對象。我們可以修改JSON以直接保存一個水果數組:
[
{
"id": 100,
"name": "Banana"
},
{
"id": 101,
"name": "Apple"
}
]
這次,我們的路由幾乎相同,但是我們將其設置為專門用於JSON數組:
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
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 {
MockEndpoint mock = getMockEndpoint("mock:marshalledObject");
mock.expectedMessageCount(1);
mock.message(0).body().isInstanceOf(List.class);
String json = readJsonFromFile("/json/fruit-array.json");
template.sendBody("direct:jsonInput", json);
assertMockEndpointsSatisfied();
@SuppressWarnings("unchecked")
List<Fruit> fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(List.class);
assertNotNull("Fruit lists should not be null", fruitList);
// more standard assertions
}
但是,與上一節中看到的測試相比,存在兩個細微的差異:
- 我們首先要設置模擬期望,
List.class
直接包含一個具有List.class
的主體 - 當我們以
List.class
獲取消息正文時,我們將收到有關類型安全的標準警告-因此使用@SuppressWarnings(“unchecked”)
六,結論
在這篇簡短的文章中,我們已經看到了兩種使用駱駝消息路由和camel-jackson
組件解組JSON數組的簡單方法。