【问题标题】:Get all the keys in a JSON string JsonNode in java在java中获取JSON字符串JsonNode中的所有键
【发布时间】:2025-12-01 08:55:01
【问题描述】:

我有一个 json 字符串,我需要验证它并在 json 字符串中找到除列表之外的任何其他键。示例 json 字符串是

{
    "required" : true,
    "requiredMsg" : "Title needed",
    "choices" : [ "a", "b", "c", "d" ],
    "choiceSettings" : {
        "a" : {
            "exc" : true
        },
        "b" : { },
        "c" : { },
        "d" : {
            "textbox" : {
                "required" : true
            }
        }
    },
    "Settings" : {
        "type" : "none"
    }
}

为了只允许 json 字符串中存在预定义的键,我想获取 json 字符串中的所有键。如何获取 json 字符串中的所有键。我正在使用 jsonNode。到目前为止我的代码是

        JsonNode rootNode = mapper.readTree(option);
        JsonNode reqiredMessage = rootNode.path("reqiredMessage");             
        System.out.println("msg   : "+  reqiredMessage.asText());            
        JsonNode drNode = rootNode.path("choices");
        Iterator<JsonNode> itr = drNode.iterator();
        System.out.println("\nchoices:");
        while (itr.hasNext()) {
            JsonNode temp = itr.next();
            System.out.println(temp.asText());
        }    

如何使用JsonNode从json字符串中获取所有键

【问题讨论】:

  • 你也想要嵌套键。我的意思是Settings.typechoiceSettings.exc

标签: java json jackson jsonnode


【解决方案1】:

接受的解决方案不支持 json 中的列表。这是我的建议:

public List<String> getAllNodeKeys(String json) throws JsonProcessingException {
    Map<String, Object> treeMap = objectMapper.readValue(json, new TypeReference<>() {
    });
    return findKeys(treeMap, new ArrayList<>());
}

private List<String> findKeys(Map<String, Object> treeMap, List<String> keys) {
    treeMap.forEach((key, value) -> {
        if (value instanceof LinkedHashMap) {
            LinkedHashMap map = (LinkedHashMap) value;
            findKeys(map, keys);
        } else if (value instanceof List) {
            ArrayList list = (ArrayList) value;
            list.forEach(map -> findKeys((LinkedHashMap) map, keys));

        }
        keys.add(key);
    });

    return keys;
}

【讨论】:

  • - 虽然您的回答可能会解决问题,但 including an explanation 关于如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提出问题的人。您可以编辑您的答案以添加解释并指出适用的限制和假设。 - [来自评论]()
【解决方案2】:

接受的答案效果很好,但发出警告,“类型安全:Map 类型的表达式需要未经检查的转换以符合 Map &lt;String, Object&gt;

This answer 导致我将该行更改为以下内容以消除警告:

Map<String, Object> treeMap = mapper.readValue(json, new TypeReference<Map<String, Object>>() {}); 

【讨论】:

    【解决方案3】:

    应该这样做。

    Map<String, Object> treeMap = mapper.readValue(json, Map.class);
    
    List<String> keys  = Lists.newArrayList();
    List<String> result = findKeys(treeMap, keys);
    System.out.println(result);
    
    private List<String> findKeys(Map<String, Object> treeMap , List<String> keys) {
        treeMap.forEach((key, value) -> {
          if (value instanceof LinkedHashMap) {
            Map<String, Object> map = (LinkedHashMap) value;
            findKeys(map, keys);
          }
          keys.add(key);
        });
    
        return keys;
      }
    

    这会将结果打印为

    [required, requiredMsg, choices, exc, a, b, c, required, textbox, d, choiceSettings, type, Settings]
    

    【讨论】:

    • 是否可以专门获取choiceSettingsexc, a, b, c, required, textbox, d 或者如果我需要` textbox` 键,它应该返回required
    • el magnifeco!谢谢
    【解决方案4】:

    forEach 将遍历 JsonNode 的子代(打印时转换为 String),fieldNames() 在键上获得 Iterator&lt;String&gt;。以下是打印示例 JSON 元素的一些示例:

    JsonNode rootNode = mapper.readTree(option);
    
    System.out.println("\nchoices:");
    rootNode.path("choices").forEach(System.out::println);
    
    System.out.println("\nAllKeys:");
    rootNode.fieldNames().forEachRemaining(System.out::println);
    
    System.out.println("\nChoiceSettings:");
    rootNode.path("choiceSettings").fieldNames().forEachRemaining(System.out::println);
    

    您可能在某些时候需要fields() 来返回Iterator&lt;Entry&lt;String, JsonNode&gt;&gt;,以便您可以迭代键、值对。

    【讨论】:

    • 使用 rootNode.fieldNames().forEachRemaining(System.out::println);如何将输出添加到列表 (List allInput) 而不是打印它
    • rootNode.fieldNames().forEachRemaining(oneInput -> allInput.add(oneInput));