從 JSONObject 中提取平面鍵和巢狀鍵
1. 簡介
處理 JSON 時,
JSONObject
類別中的資料(通常由org.json –
是基本建構塊。常見的需求是從 JSON 物件中提取所有鍵以用於驗證、轉換或資料映射等目的。 keySet()
方法提供了一種簡單有效的方法來將所有這些鍵作為Set<String>
獲取,使我們能夠輕鬆地對它們進行迭代或執行過濾或轉換等操作。
本質上,Java 中的JSONObject
的行為非常類似於Map<String, Object>
。每個鍵都是一個String
,關聯值可以是原語、陣列、其他JSONObjects
,甚至是 null。 keySet()
方法可在JSON-Java (org.json)
函式庫等實作中使用,它提供了一種直接存取這些鍵的方法,而無需手動轉換或遍歷物件。我們可以在該庫的介紹中找到更多範例。
2. 基本用法:從扁平 JSON 物件中提取鍵
讓我們從一個基本用例開始,從平面(非巢狀)JSON 物件中提取鍵。下面是一個可以實現這一目標的方法:
public static Set<String> extractKeys(String jsonString) {
JSONObject jsonObject = new JSONObject(jsonString);
return jsonObject.keySet();
}
此方法將 JSON 字串解析為JSONObject
,然後呼叫keySet()
來檢索所有頂層鍵。為了驗證此行為,讓我們編寫一個快速單元測試:
@Test
public void givenFlatJson_whenExtractKeys_thenReturnAllTopLevelKeys() {
String json = "{\"name\":\"Jane\", \"name_id\":12345, \"city\":\"Vancouver\"}";
keys = JSONGetValueWithKeySet.extractKeys(json);
assertTrue(keys.contains("name"));
assertTrue(keys.contains("name_id"));
assertTrue(keys.contains("city"));
assertEquals(3, keys.size());
}
因此,我們從平面結構中準確地提取了所有預期的密鑰。
3. 巢狀 JSON 處理:從巢狀物件中提取鍵
扁平結構易於管理,但如果 JSON 包含巢狀物件怎麼辦?在這種情況下,我們可以使用遞歸方法來遍歷結構並收集每一層的鍵。為了保持清晰,我們將使用點符號來表示層次結構(例如user.name
或city.id
)。
讓我們實現這個遞歸遍歷:
public static void extractNestedKeys(JSONObject jsonObject, String parentKey, Set<String> result) {
for (String key : jsonObject.keySet()) {
String fullKey = parentKey.isEmpty() ? key : parentKey + "." + key;
Object value = jsonObject.get(key);
result.add(fullKey);
if (value instanceof JSONObject) {
extractNestedKeys((JSONObject) value, fullKey, result);
}
}
}
透過這種方法,我們遍歷每個鍵值對,如果遇到另一個JSONObject
,我們將以遞歸方式繼續遍歷,同時保留鍵的完整路徑。
讓我們透過相應的單元測試來驗證這一點:
@Test
public void givenNestedJson_whenExtractNestedKeys_thenReturnAllKeysWithHierarchy() {
String json = "{"
+ "\"user\": {"
+ "\"id\": 101,"
+ "\"name\": \"Gregory\""
+ "},"
+ "\"city\": {"
+ "\"id\": 121,"
+ "\"name\": \"Calgary\""
+ "},"
+ "\"region\": \"CA\""
+ "}";
JSONObject jsonObject = new JSONObject(json);
Set<String> actualKeys = new HashSet<>();
JSONGetValueWithKeySet.extractNestedKeys(jsonObject, "", actualKeys);
Set<String> expectedKeys = Set.of("user", "user.id", "user.name", "city",
"city.id", "city.name", "region");
assertEquals(expectedKeys, actualKeys);
}
這樣,我們確保捕獲所有嵌套鍵,並且層次結構準確地反映在鍵名中。
4.最佳實踐
使用JSONObject
結構時我們應該記住的主要方面是安全檢查和高效使用。我們總是會在轉換之前檢查是否為null
並確保該值是JSONObject
,以避免出現異常。我們應該將keySet()
傳回的集合視為不可變的,因為它由原始物件支援。因此,如果我們修改集合(例如,透過刪除鍵),它將影響JSONObject
本身。如果我們的 JSON 包含數組,我們會考慮是否也需要從這些數組中的物件中提取鍵。最後,透過使用keySet(),
即使對於大型 JSON 對象,我們也能確保一定的效率,因為我們避免了在必要時轉換為其他資料結構(如Map
的開銷。
5. 結論
使用keySet()
方法從 Java 中的JSONObject
中提取鍵簡單而有效率。對於平面 JSON 對象,直接迭代keySet()
就夠了。對於嵌套結構,遞歸方法可確保捕捉所有鍵,即使在層次結構的深處也是如此。當遵循最佳實踐(例如正確的類型檢查和理解返回集合的可變性)時,我們可以在 Java 應用程式中可靠地使用 JSON 鍵。本文的完整原始碼可以在 GitHub 上找到。