1. 概述
當我們在 Java 中處理 JSON 數據時,我們經常遇到的任務之一是從中提取所有鍵。起初看起來很簡單,畢竟 GSON 使解析 JSON 變得非常簡單。然而,一旦我們的 JSON 開始嵌套,情況就會變得更加複雜。
在本教程中,我們將學習如何使用 GSON 從 JsonObject 中獲取所有鍵,包括嵌套的鍵。我們還將編寫單元測試以確保我們的解決方案能夠正確工作。
2. 我們需要什麼?
假設我們收到來自 API 的 JSON 響應,並且我們想要:
- 驗證特定鍵是否存在。
- 記錄所有鍵以供調試。
- 扁平化結構以便於比較或處理。
如果我們的 JSON 看起來很簡單,例如如下所示:
{
"name": "Henry",
"email": "[email protected]",
"age": 25
}然後調用 jsonObject.keySet() 會返回所有鍵:
[name, email, age]但一旦我們處理嵌套的 JSON 時:
{
"name": "Henry",
"email": "[email protected]",
"address": {
"city": "New York",
"zip": "10001"
}
}jsonObject.keySet() 只會返回:
[name, email, address]我們丟失了嵌套鍵,例如 address.city 和 address.zip。如果想要一個完整的鍵列表,這就不太理想。
3. 如何解決?
我們可以通過編寫遞歸方法來解決這個問題。 首先,我們可以使用 GSON 庫。它是一個輕量級且廣泛使用的 JSON 庫。
我們可以添加 GSON 到我們的 pom.xml 中,使用 Maven 依賴:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>讓我們來查看一下實現:
public static List<String> getAllKeys(JsonObject jsonObject) {
List<String> keys = new ArrayList<>();
extractKeys("", jsonObject, keys);
return keys;
}
private static void extractKeys(String prefix, JsonObject jsonObject, List<String> keys) {
Set<String> jsonKeys = jsonObject.keySet();
for (String key : jsonKeys) {
String fullKey = prefix.isEmpty() ? key : prefix + "." + key;
keys.add(fullKey);
JsonElement element = jsonObject.get(key);
if (element.isJsonObject()) {
extractKeys(fullKey, element.getAsJsonObject(), keys);
}
}
}讓我們理解一下實現方式:
- 我們首先從方法 getAllKeys() 開始。它準備一個列表並調用 extractKeys()。
- extractKeys() 方法遍歷當前對象的鍵。
- 如果值是另一個 JsonObject,我們遞歸地調用相同的函數。
- 為了使鍵更有意義,我們添加前綴。而不是僅僅存儲城市,我們存儲 address.city。
讓我們看一下支持的測試用例:
@Test
void givenJson_whenTopLevelKeys_thenGetAllKeys() {
String json = "{ \"name\":\"Henry\", \"email\":\"[email protected]\", \"age\":25 }";
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
List<String> keys = JsonKeyExtractor.getAllKeys(jsonObject);
assertEquals(3, keys.size());
assertTrue(keys.contains("name"));
assertTrue(keys.contains("email"));
assertTrue(keys.contains("age"));
}
@Test
void givenJson_whenNestedKeys_thenGetAllKeys() {
String json = "{ \"address\": { \"city\":\"New York\", \"zip\":\"10001\" } }";
JsonObject jsonObject = JsonParser.parseString(json).getAsJsonObject();
List<String> keys = JsonKeyExtractor.getAllKeys(jsonObject);
assertEquals(3, keys.size());
assertTrue(keys.contains("address"));
assertTrue(keys.contains("address.city"));
assertTrue(keys.contains("address.zip"));
}這樣,我們不會錯過任何內容,無論JSON嵌套的深度如何。
4. 我們能在哪裏使用它?
現在我們已經解決了這個問題,讓我們思考一下這個在實際項目中可以發揮作用的地方:
- 驗證:確保傳入的 JSON 中存在所需的鍵。
- 審計:記錄 JSON 負載的結構,用於調試或合規性檢查。
- 扁平化數據:為不處理嵌套 JSON 的工具準備數據。
- 模式發現:在不手動檢查負載的情況下探索未知的 API。
5. 結論
在本文中,我們構建了一個簡單的遞歸實用程序,使用 GSON 從 JsonObject 中提取所有鍵。通過處理嵌套對象,我們可以確保沒有鍵遺漏。這種方法的優點在於它具有靈活性,並且如果需要,我們可以進一步擴展它以處理數組或應用過濾器,例如僅收集葉子鍵。
現在,每當我們需要使用 Java 處理 JSON 時,我們都會擁有一個可靠的方法來獲取所有鍵。