在 Java 中對 JSON 物件進行排序
1. 概述
JSON 是一種廣泛使用的結構化資料格式,通常用於大多數現代 API 和資料服務。由於其輕量級特性以及與 JavaScript 的兼容性,它在 Web 應用程式中特別受歡迎。
有時,在獲取 JSON 的應用程式中顯示資料之前對資料進行排序可能很有用。
在本快速教程中,我們將看到幾種在 Java 中對 JSON 物件進行排序的方法。
2. 入門
讓我們開始定義一個相對簡單的 JSON 結構,該結構對一些想像的太陽事件進行建模:
{
"solar_events": [
{
"event_name": "Solar Eclipse",
"date": "2024-04-08",
"coordinates": {
"latitude": 37.7749,
"longitude": -122.4194
},
"size": "Large",
"speed_km_per_s": 1000
},
{
"event_name": "Solar Flare",
"date": "2023-10-28",
"coordinates": {
"latitude": 0,
"longitude": 0
},
"size": "Small",
"speed_km_per_s": 100
},
{
"event_name": "Sunspot",
"date": "2023-11-15",
"coordinates": {
"latitude": 15,
"longitude": -75
},
"size": "Large",
"speed_km_per_s": 1500
},
{
"event_name": "Coronal Mass Ejection",
"date": "2024-01-10",
"coordinates": {
"latitude": -5,
"longitude": 80
},
"size": "Medium",
"speed_km_per_s": 500
}
]
}
在本教程中,這個 JSON 文件將是我們範例的重點。
3.利用傑克遜
在第一個範例中,我們將了解 Jackson,一個用於處理 JSON 資料的多用途 Java 函式庫。
首先,我們需要將jackson-databind
依賴項加入pom.xml
中:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.2</version>
</dependency>
我們還需要定義一些簡單的 POJO 對象,我們可以使用它們將 JSON 字串反序列化為 Java 對象:
class SolarEvent {
@JsonProperty("event_name")
private String eventName;
@JsonProperty("date")
private String date;
@JsonProperty("coordinates")
private Coordinates coordinates;
@JsonProperty("type")
private String type;
@JsonProperty("class")
private String eventClass;
@JsonProperty("size")
private String size;
@JsonProperty("speed_km_per_s")
private int speedKmPerS;
// Getters and Setters
}
class Coordinates {
@JsonProperty("latitude")
private double latitude;
@JsonProperty("longitude")
private double longitude;
// Getters and setters
}
我們還將定義一個容器物件來保存事件列表:
class SolarEventContainer {
@JsonProperty("solar_events")
private List<SolarEvent> solarEvents;
//Getters and setters
}
現在,我們可以繼續編寫一個簡單的單元測試來驗證我們可以使用給定的屬性對太陽事件列表進行排序:
@Test
void givenJsonObjects_whenUsingJackson_thenSortedBySpeedCorrectly() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
SolarEventContainer container =
objectMapper.readValue(new File("src/test/resources/solar_events.json"),
SolarEventContainer.class);
List<SolarEvent> events = container.getSolarEvents();
Collections.sort(events, Comparator.comparingInt(event -> event.getSpeedKmPerS()));
assertEquals(100, events.get(0).getSpeedKmPerS());
assertEquals(500, events.get(1).getSpeedKmPerS());
assertEquals(1000, events.get(2).getSpeedKmPerS());
assertEquals(1500, events.get(3).getSpeedKmPerS());
}
我們的第一個目標是解析 JSON 並將其反序列化到我們的物件模型中。為此,我們使用了 Jackson 的標準ObjectMapper
。我們使用readValue()
方法從檔案中讀取 JSON 並將 JSON 轉換為SolarEventContainer
物件。
現在我們有了一個 Java 物件模型,我們可以繼續根據類別中的任何屬性對物件進行排序。對於排序,我們使用 lambda 表達式定義一個Comparator
,並使用comparingInt()
靜態工廠來使用getSpeedKmPerS()
方法對事件進行排序。
最後,我們的測試確認速度屬性正確地對事件進行了排序。
4.使用Gson
現在,讓我們來看看使用另一個流行的 JSON 處理庫 Gson 的類似方法。和以前一樣,我們首先將此依賴項新增到pom.xml
中:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.11.0</version>
</dependency>
與往常一樣,最新版本可從Maven 儲存庫取得。
有時,可能無法總是使用我們自己的內部 Java 物件模型,因此在本範例中,我們將了解如何使用可直接從此程式庫中取得的 JSON Java 物件:
@Test
public void givenJsonObject_whenUsingGson_thenSortedBySizeCorrectly() throws FileNotFoundException {
JsonReader reader = new JsonReader(new FileReader("src/test/resources/solar_events.json"));
JsonElement element = JsonParser.parseReader(reader);
JsonArray events = element.getAsJsonObject().getAsJsonArray("solar_events");
List<JsonElement> list = events.asList();
Collections.sort(list, (a, b) -> {
double latA = a.getAsJsonObject()
.getAsJsonObject("coordinates")
.get("latitude")
.getAsDouble();
double latB = b.getAsJsonObject()
.getAsJsonObject("coordinates")
.get("latitude")
.getAsDouble();
return Double.compare(latA, latB);
});
assertEquals(-5, getJsonAttributeAsInt(list.get(0)));
assertEquals(0, getJsonAttributeAsInt(list.get(1)));
assertEquals(15, getJsonAttributeAsInt(list.get(2)));
assertEquals(37, getJsonAttributeAsInt(list.get(3)));
}
private int getJsonAttributeAsInt(JsonElement element) {
return element.getAsJsonObject()
.getAsJsonObject("coordinates")
.get("latitude")
.getAsInt();
}
正如我們所看到的,我們使用類似的方法來讀取範例 JSON 文件,但這一次,我們檢索JsonElement
物件列表,它代表solar_events.json
檔案中的每個條目。
同樣,我們現在可以使用Collections.sort
方法對清單中的元素進行排序,方法是提供自訂比較器來解析 JSON 物件並選擇所需的值。這肯定比前面的範例更冗長,如果我們的 JSON 結構發生變更或我們錯誤地輸入了 JSON 物件或屬性名稱,則很容易出錯。
最後,這次,我們使用緯度值來檢查元素是否已正確排序。我們也提供了一個小實用方法來幫助我們從 JSON 元素中提取值。
5. 結論
在這篇短文中,我們學習如何使用兩個流行的 JSON 處理 Java 函式庫對 JSON 物件進行排序。
在第一個範例中,我們了解如何將我們自己的 Java 物件模型與流行的 Jackson 庫一起使用。最近,我們學習如何直接使用 Gson 函式庫提供的物件模型。
與往常一樣,本文的完整原始碼可以在 GitHub 上取得。