知識庫 / JSON / Jackson RSS 訂閱

使用 JsonNode 獲取 JSON 字符串中的所有鍵

Jackson
HongKong
6
09:50 PM · Dec 05 ,2025

1. 概述

本教程將探討使用 <em >JsonNode</em >> 從 JSON 中提取所有嵌套鍵的不同方法。我們將嘗試遍歷一個 JSON 字符串並以列表的形式收集鍵名。

2. 簡介

Jackson 庫使用樹模型來表示 JSON 數據。 樹模型為我們提供了一種高效的方式來與層次化數據交互。

JSON 對象表示為樹模型中的節點。 這使得更容易對 JSON 內容執行 CRUD 操作。

2.1. ObjectMapper

我們使用 ObjectMapper 類的方法來讀取 JSON 內容。  ObjectMapper.readTree() 方法反序列化 JSON 並構建 JsonNode 實例的樹結構。 它接受 JSON 源作為輸入,並返回創建的樹模型根節點。 隨後,我們可以使用根節點來遍歷整個 JSON 樹。

該樹模型不限於讀取常規 Java 對象。 JSON 字段與樹模型之間存在一對一的映射關係。 因此,無論是 POJO 還是其他對象,都可以表示為一個節點。 這樣,我們就可以靈活地將 JSON 內容表示為通用節點

要了解更多信息,請參閲我們的關於 Jackson ObjectMapper 文章。

2.2. `JsonNode

The JsonNode 類代表 JSON 樹模型中的節點。它能夠表達以下 JSON 數據類型:Array, Binary, Boolean, Missing, Null, Number, Object, POJO, String。這些數據類型定義在 JsonNodeType 枚舉 中。

3. 從 JSON 中獲取鍵

我們將在本文中使用以下 JSON 作為輸入:

{
   "Name":"Craig",
   "Age":10,
   "BookInterests":[
      {
         "Book":"The Kite Runner",
         "Author":"Khaled Hosseini"
      },
      {
         "Book":"Harry Potter",
         "Author":"J. K. Rowling"
      }
   ],
   "FoodInterests":{
      "Breakfast":[
         {
            "Bread":"Whole wheat",
            "Beverage":"Fruit juice"
         },
         {
            "Sandwich":"Vegetable Sandwich",
            "Beverage":"Coffee"
         }
      ]
   }
}

我們這裏使用 String 對象作為輸入,但可以從不同的源讀取 JSON 內容,例如 Filebyte[]URLInputStreamJsonParser 等。

現在,我們來討論從 JSON 中獲取鍵的不同方法。

3.1. 使用 fieldNames 方法

我們可以使用 fieldNames 方法來從 JsonNode 實例中獲取嵌套字段名稱。該方法 僅返回直接嵌套字段的名稱

讓我們用一個簡單的例子來嘗試一下:

public List<String> getKeysInJsonUsingJsonNodeFieldNames(String json, ObjectMapper mapper) throws JsonMappingException, JsonProcessingException {

    List<String> keys = new ArrayList<>();
    JsonNode jsonNode = mapper.readTree(json);
    Iterator<String> iterator = jsonNode.fieldNames();
    iterator.forEachRemaining(e -> keys.add(e));
    return keys;
}

我們將會獲取以下鍵值:

[Name, Age, BookInterests, FoodInterests]

為了獲取所有嵌套節點,需要調用在每個級別節點上的 fieldNames() 方法

public List<String> getAllKeysInJsonUsingJsonNodeFieldNames(String json, ObjectMapper mapper) throws JsonMappingException, JsonProcessingException {

    List<String> keys = new ArrayList<>();
    JsonNode jsonNode = mapper.readTree(json);
    getAllKeysUsingJsonNodeFieldNames(jsonNode, keys);
    return keys;
}
private void getAllKeysUsingJsonNodeFields(JsonNode jsonNode, List<String> keys) {

    if (jsonNode.isObject()) {
        Iterator<Entry<String, JsonNode>> fields = jsonNode.fields();
        fields.forEachRemaining(field -> {
            keys.add(field.getKey());
            getAllKeysUsingJsonNodeFieldNames((JsonNode) field.getValue(), keys);
        });
    } else if (jsonNode.isArray()) {
        ArrayNode arrayField = (ArrayNode) jsonNode;
        arrayField.forEach(node -> {
            getAllKeysUsingJsonNodeFieldNames(node, keys);
        });
    }
}

首先,我們將檢查 JSON 值是否為對象或數組。如果是,我們將遍歷對象以獲取內部節點。

最終,我們將獲取 JSON 中所有存在的鍵名。

[Name, Age, BookInterests, Book, Author,
  Book, Author, FoodInterests, Breakfast, Bread, Beverage, Sandwich, Beverage]

在上面的示例中,我們還可以使用 <em >fields()</em > 方法,該方法用於從 <em >JsonNode</em > 類中獲取字段對象,而不是僅僅獲取字段名稱:

public List<String> getAllKeysInJsonUsingJsonNodeFields(String json, ObjectMapper mapper) throws JsonMappingException, JsonProcessingException {

    List<String> keys = new ArrayList<>();
    JsonNode jsonNode = mapper.readTree(json);
    getAllKeysUsingJsonNodeFields(jsonNode, keys);
    return keys;
}

private void getAllKeysUsingJsonNodeFields(JsonNode jsonNode, List<String> keys) {

    if (jsonNode.isObject()) {
        Iterator<Entry<String, JsonNode>> fields = jsonNode.fields();
        fields.forEachRemaining(field -> {
            keys.add(field.getKey());
            getAllKeysUsingJsonNodeFieldNames((JsonNode) field.getValue(), keys);
        });
    } else if (jsonNode.isArray()) {
        ArrayNode arrayField = (ArrayNode) jsonNode;
        arrayField.forEach(node -> {
            getAllKeysUsingJsonNodeFieldNames(node, keys);
        });
    }
}

3.2. 使用 <em>JsonParser</em>

我們還可以使用 `JsonParser` 類進行低級別的 JSON 解析。`JsonParser` 類會從給定的 JSON 內容中創建一系列可迭代的標記(tokens)。標記類型由 `enums` 在 `JsonToken` 類中指定,如下所示:

  • NOT_AVAILABLE
  • START_OBJECT
  • END_OBJECT
  • START_ARRAY
  • FIELD_NAME
  • VALUE_EMBEDDED_OBJECT
  • VALUE_STRING
  • VALUE_NUMBER_INT
  • VALUE_NUMBER_FLOAT
  • VALUE_TRUE
  • VALUE_FALSE
  • VALUE_NULL

在通過 `JsonParser` 進行迭代時,我們可以檢查標記類型並執行所需的操作。 讓我們為我們的示例 JSON 字符串獲取所有字段名稱:

public List<String> getKeysInJsonUsingJsonParser(String json, ObjectMapper mapper) throws IOException {

    List<String> keys = new ArrayList<>();
    JsonNode jsonNode = mapper.readTree(json);
    JsonParser jsonParser = jsonNode.traverse();
    while (!jsonParser.isClosed()) {
        if (jsonParser.nextToken() == JsonToken.FIELD_NAME) {
            keys.add((jsonParser.getCurrentName()));
        }
    }
    return keys;
}

在這裏,我們使用了 JsonNode 類中的 traverse() 方法來獲取 JsonParser 對象。 類似地,我們也可以使用 JsonFactory 創建 JsonParser 對象。

public List<String> getKeysInJsonUsingJsonParser(String json) throws JsonParseException, IOException {

    List<String> keys = new ArrayList<>();
    JsonFactory factory = new JsonFactory();
    JsonParser jsonParser = factory.createParser(json);
    while (!jsonParser.isClosed()) {
        if (jsonParser.nextToken() == JsonToken.FIELD_NAME) {
            keys.add((jsonParser.getCurrentName()));
        }
    }
    return keys;
}

因此,我們將會從示例 JSON 內容中提取出所有關鍵名稱:

[Name, Age, BookInterests, Book, Author,
  Book, Author, FoodInterests, Breakfast, Bread, Beverage, Sandwich, Beverage]

請注意,與本文中介紹的其他方法相比,這段代碼的簡潔性如何。

3.3. 使用Map

我們可以使用 ObjectMapper 類中的 <em/>readValue()<em/> 方法將 JSON 內容反序列化為Map。 這樣,我們就可以在迭代Map對象時提取 JSON 元素。 讓我們使用這種方法從我們的示例 JSON 中獲取所有鍵:

public List<String> getKeysInJsonUsingMaps(String json, ObjectMapper mapper) throws JsonMappingException, JsonProcessingException {
    List<String> keys = new ArrayList<>();
    Map<String, Object> jsonElements = mapper.readValue(json, new TypeReference<Map<String, Object>>() {
    });
    getAllKeys(jsonElements, keys);
    return keys;
}

private void getAllKeys(Map<String, Object> jsonElements, List<String> keys) {

    jsonElements.entrySet()
        .forEach(entry -> {
            keys.add(entry.getKey());
            if (entry.getValue() instanceof Map) {
                Map<String, Object> map = (Map<String, Object>) entry.getValue();
                getAllKeys(map, keys);
            } else if (entry.getValue() instanceof List) {
                List<?> list = (List<?>) entry.getValue();
                list.forEach(listEntry -> {
                    if (listEntry instanceof Map) {
                        Map<String, Object> map = (Map<String, Object>) listEntry;
                        getAllKeys(map, keys);
                    }
                });
            }
        });
}

在這種情況下,在獲取頂層節點之後,我們還將遍歷具有值為對象(映射)或數組的JSON對象,以獲取嵌套節點。

4. 結論

在本文中,我們學習了從 JSON 內容中讀取鍵名不同的方法。因此,我們可以將本文中討論的遍歷邏輯擴展到執行其他操作,具體操作針對 JSON 元素時,如需要。

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

發佈 評論

Some HTML is okay.