You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何使用SnakeYaml安全提取YAML文件嵌套值

实现方案

你当前的循环思路只处理了第一层Map结构,遇到多层嵌套、根节点为列表的场景会失效,且直接使用默认Yaml构造器加载未知文件存在安全风险,可通过递归遍历+安全加载的方式实现任意结构YAML的嵌套值提取,具体实现如下:

安全加载说明

SnakeYAML默认构造器支持将YAML标签反序列化为任意Java对象,加载未知来源文件时存在远程代码执行漏洞,解析前必须配置SafeConstructor禁用危险的反序列化能力。

可直接运行的实现代码

import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.SafeConstructor;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

public class UniversalYamlParser {

    public static void main(String[] args) throws Exception {
        File targetYamlFile = new File("path/to/your/file.yaml");
        // 初始化安全解析实例,禁止任意类反序列化
        Yaml yaml = new Yaml(new SafeConstructor());
        // 加载结果统一用Object接收,避免根节点为List时强转报错
        Object rootNode = yaml.load(FileUtils.readFileToString(targetYamlFile, StandardCharsets.UTF_8));
        // 从根节点开始递归遍历,初始路径为空
        traverseNestedNode("", rootNode);
    }

    /**
     * 递归遍历任意深度的YAML节点,自动识别Map、List、基础值类型
     * @param currentPath 当前节点的完整层级路径,如datasource.url、user[0].name
     * @param node 当前待处理的节点对象
     */
    private static void traverseNestedNode(String currentPath, Object node) {
        // 处理空值
        if (node == null) {
            System.out.printf("路径:%s | 值:null%n", currentPath);
            return;
        }

        // 节点为键值对结构,递归遍历每个子键
        if (node instanceof Map<?, ?> mapNode) {
            for (Map.Entry<?, ?> entry : mapNode.entrySet()) {
                String nodeKey = entry.getKey().toString();
                String childPath = currentPath.isEmpty() ? nodeKey : currentPath + "." + nodeKey;
                traverseNestedNode(childPath, entry.getValue());
            }
            return;
        }

        // 节点为列表/数组结构,按索引遍历每个元素
        if (node instanceof List<?> listNode) {
            for (int index = 0; index < listNode.size(); index++) {
                String childPath = currentPath + "[" + index + "]";
                traverseNestedNode(childPath, listNode.get(index));
            }
            return;
        }

        // 节点为基础类型(字符串、数字、布尔值等),直接输出/存储值
        System.out.printf("路径:%s | 值:%s | 值类型:%s%n",
                currentPath,
                node,
                node.getClass().getSimpleName());
    }
}

适配说明

  • 如果你使用的是Java 16以下版本,将代码中instanceof Map<?, ?> mapNode、instanceof List<?> listNode的模式匹配写法改为传统类型判断+手动强转即可,核心遍历逻辑不需要修改。
  • 原有代码中StrandardCharsets为拼写错误,JDK提供的标准字符集类正确名为StandardCharsets。
  • 如果需要按指定路径提取值(比如提取server.port对应的值),只需要在遍历到基础值节点时判断currentPath是否和目标路径匹配即可,不需要提前预知YAML的整体结构。
  • 该实现会自动处理任意嵌套深度,不需要手动写多层循环,也不会漏掉列表类型的嵌套节点。

内容的提问来源于stack exchange,提问作者AwesomeDude091

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 15:18:13