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

Jackson
Remote
0
09:34 PM · Nov 30 ,2025

1. 概述

在本教程中,我們將探討如何使用 JsonNode 從 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

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

3. Getting Keys From JSON

We’re using the following JSON as input in this article:

{
   "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"
         }
      ]
   }
}

Here we’re using a String object as input, but we can read JSON content from different sources, such as Filebyte[], URLInputStreamJsonParser, etc.

Now let’s discuss different approaches to fetch keys from a JSON.

3.1. Using fieldNames

We can use the fieldNames() method on a JsonNode instance to fetch the nested field names. It returns names of direct nested fields only.

Let’s try it with a simple example:

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;
}

We’ll get the following keys:

[Name, Age, BookInterests, FoodInterests]

In order to get all the inner nested nodes, we need to call the fieldNames() method on nodes at each level:

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);
        });
    }
}

First, we’ll check whether a JSON value is an object or array. If yes, we’ll traverse the value object as well to fetch inner nodes.

As a result, we’ll get all the key names present in JSON:

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

In the above example, we can also use the fields() method of the JsonNode class to get field objects instead of just field names:

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. Using JsonParser

We can also use the JsonParser class for low-level JSON parsingJsonParser creates a sequence of iterable tokens from the given JSON content. Token types are specified as enums in the JsonToken class, as listed below:

  • 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

While iterating using JsonParser, we can check the token type and perform required operations. Let’s fetch all the field names for our example JSON string:

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;
}

Here, we’ve used the traverse() method of the JsonNode class to get the JsonParser object. Similarly, we can create a JsonParser object using JsonFactory as well:

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;
}

As a result, we’ll get all the key names extracted from the example JSON content:

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

Notice how concise the code is if we compare it to the other approaches we presented in this article.

 3.3. Using Map

We can use the readValue() method of the ObjectMapper class to deserialize JSON content to a Map. Consequently, we can extract JSON elements while iterating over the Map object. Let’s try to fetch all keys from our example JSON using this approach:

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);
                    }
                });
            }
        });
}

Also in this case, after getting top-level nodes, we’ll traverse the JSON objects that have values as either objects (maps) or arrays to get nested nodes.

4. 結論

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

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

發佈 評論

Some HTML is okay.