如何使用SnakeYAML将带标签YAML对象转为含objectType的Java Map
基于SnakeYAML的带标签YAML转带objectType的Map解决方案
核心实现思路:自定义SnakeYAML的Constructor构造器,拦截所有带自定义标签的映射节点,在构造Map对象时额外插入objectType字段,值为标签去掉前缀!的名称。
实现代码
1. 自定义构造器类
import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.nodes.MappingNode; import org.yaml.snakeyaml.nodes.Node; import org.yaml.snakeyaml.nodes.Tag; import java.util.Map; public class TaggedToObjectTypeConstructor extends Constructor { @Override protected Object constructObject(Node node) { // 仅处理非内置标签的映射节点,排除SnakeYAML自带的!!map、!!int等内置标签 if (node instanceof MappingNode mappingNode && !node.getTag().isBuiltIn()) { // 先按默认逻辑构造Map对象 Map<String, Object> map = (Map<String, Object>) super.constructObject(node); // 提取标签名称,去掉开头的! String tagName = node.getTag().getValue().substring(1); // 插入objectType字段 map.put("objectType", tagName); return map; } // 其他类型节点走默认解析逻辑 return super.constructObject(node); } }
2. 调用示例
import org.yaml.snakeyaml.Yaml; import java.util.Map; public class YamlParseDemo { public static void main(String[] args) { // 初始化携带自定义构造器的Yaml实例 Yaml yaml = new Yaml(new TaggedToObjectTypeConstructor()); // 待解析的YAML内容,也可传入文件输入流等其他数据源 String yamlContent = """ !ControlGroup name: myGroup controls: - !Button name: button1 size: 10 - !Knob name: knob1 maxValue: 11 size: 7 """; // 解析得到嵌套Map结构 Map<String, Object> result = yaml.load(yamlContent); // 验证结果 System.out.println(result); } }
效果说明
解析后的结构完全符合需求:
- 根Map包含
objectType: "ControlGroup"条目 - controls列表中的两个子Map分别包含
objectType: "Button"和objectType: "Knob"条目 - YAML中原有的所有字段均会完整保留
注意事项
- 无需额外配置即可支持多级嵌套的带标签映射,构造器会自动递归处理所有层级的符合条件的节点
- 若存在不需要解析的特殊标签,可自行在判断逻辑中增加标签白名单过滤
- 解析得到的Map可直接搭配Jackson等JSON序列化库直接输出为符合要求的JSON格式
内容的提问来源于stack exchange,提问作者user10264746
相关产品推荐
相关产品推荐

