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

如何使用SnakeYaml为指定节点设置动态ScalarStyle

针对特定节点(expression)设置SnakeYAML双引号标量样式的实现方法

要实现仅对所有expression节点强制使用双引号标量样式,同时保持其他节点的默认纯量格式,可以通过自定义Representer并跟踪节点路径来实现,核心思路是拦截序列化过程中所有名为expression的标量节点,强制指定其样式。

实现步骤

1. 自定义Representer类

继承SnakeYAML的Representer,通过维护当前节点路径来识别expression节点,并重写标量序列化逻辑:

import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import java.util.Deque;
import java.util.LinkedList;

public class CustomExpressionRepresenter extends Representer {
    // 用双端队列跟踪当前序列化的节点路径
    private final Deque<String> currentNodePath = new LinkedList<>();

    @Override
    protected Node representData(Object data) {
        // 处理Map键值对,记录当前键到路径中
        if (data instanceof java.util.Map.Entry) {
            String key = ((java.util.Map.Entry<?, ?>) data).getKey().toString();
            currentNodePath.push(key);
            Node node = super.representData(data);
            currentNodePath.pop();
            return node;
        }
        // 处理列表元素,父节点为expressions时不修改路径,仅确保子节点能被识别
        else if (data instanceof Iterable && currentNodePath.peek() != null && currentNodePath.peek().equals("expressions")) {
            return super.representData(data);
        }
        return super.representData(data);
    }

    @Override
    protected Node representScalar(Tag tag, String value, Character style) {
        // 判断当前路径最后一个节点是否为expression,是则强制双引号样式
        if (!currentNodePath.isEmpty() && currentNodePath.peek().equals("expression")) {
            return super.representScalar(tag, value, '"');
        }
        // 其他节点保持默认样式
        return super.representScalar(tag, value, style);
    }
}

2. 使用自定义Representer序列化

在创建YAML实例时传入自定义的Representer,即可实现目标效果:

import org.yaml.snakeyaml.Yaml;
import java.util.*;

public class YamlSerializationDemo {
    public static void main(String[] args) {
        // 构建测试负载
        Map<String, Object> config = new HashMap<>();
        Map<String, Object> specialConfig = new HashMap<>();
        List<Map<String, String>> expressions = new ArrayList<>();
        
        expressions.add(Map.of("expression", "a > b && c == 'test'"));
        expressions.add(Map.of("expression", "status in ['success', 'pending']"));
        
        specialConfig.put("expressions", expressions);
        specialConfig.put("enabled", true); // 布尔值保持默认纯量样式
        config.put("zzh-special-config", specialConfig);
        config.put("system-version", "v1.2.3"); // 普通字符串保持默认

        // 初始化自定义YAML实例
        CustomExpressionRepresenter representer = new CustomExpressionRepresenter();
        Yaml yaml = new Yaml(representer);
        
        // 序列化并输出结果
        String yamlOutput = yaml.dump(config);
        System.out.println(yamlOutput);
    }
}

核心逻辑说明

  • 节点路径跟踪:通过currentNodePath队列记录当前序列化的节点层级,当处理Map的键值对时,将键名加入队列,处理完成后弹出,确保路径始终与当前序列化位置匹配。
  • 样式强制拦截:在representScalar方法中,判断当前路径的最后一个节点是否为expression,若是则强制使用双引号('"')作为标量样式,其他节点沿用SnakeYAML的默认规则,避免布尔值、数字、普通键被错误添加双引号。
  • 通配符适配:无论expression节点出现在哪个层级(如config.xxx.expressions[].expression),只要节点名为expression,都会被正确识别并应用双引号样式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:40:31