如何使用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
相关产品推荐
相关产品推荐

