SnakeYAML对象创建控制:多态构造器标签处理异常问题
SnakeYAML多态字段Constructor标签冲突问题
场景描述
需要解析带自定义标签的YAML结构,示例如下:
enclosures: areaFoo: !circle { color: red, radius: 5.0 } areaBar: !rectangle { color: blue, height: 5.0, width: 10.0 }
预期!circle标签对应实例化model.Circle类,!rectangle标签对应model.Rectangle类。
当前实现与问题
通过注册表关联标签与对应类,重写Constructor的constructObject方法:
@Override protected Object constructObject(Node node) { Tag tag = node.getTag(); Class<?> resolvedClassByTag = registry.getClassForTag(tag); if (resolvedClassByTag != null) { logger.debug("Constructing object with tag '{}' as {}", tag, resolvedClassByTag.getName()); node.setType(resolvedClassByTag); return super.constructObject(node); } // ... 处理其他类 ... return super.constructObject(node); }
设置node.setType(resolvedClassByTag)后调用super.constructObject(node),但父方法仍会使用节点原标签查找类型,导致找不到对应类抛出错误。尝试将标签设为null会触发Tag can not be null异常。
解决方案
方案1:替换标签为对应类的默认标签
将节点标签替换为目标类的默认标签,让SnakeYAML识别并使用已设置的类型构造对象:
@Override protected Object constructObject(Node node) { Tag tag = node.getTag(); Class<?> resolvedClassByTag = registry.getClassForTag(tag); if (resolvedClassByTag != null) { logger.debug("Constructing object with tag '{}' as {}", tag, resolvedClassByTag.getName()); node.setType(resolvedClassByTag); // 替换为目标类的默认标签,覆盖原自定义标签 node.setTag(new Tag(resolvedClassByTag)); return super.constructObject(node); } // ... 处理其他类 ... return super.constructObject(node); }
方案2:直接调用constructType绕过标签查找
跳过父方法的标签查找逻辑,直接调用constructType方法使用指定类实例化对象:
@Override protected Object constructObject(Node node) { Tag tag = node.getTag(); Class<?> resolvedClassByTag = registry.getClassForTag(tag); if (resolvedClassByTag != null) { logger.debug("Constructing object with tag '{}' as {}", tag, resolvedClassByTag.getName()); // 直接使用指定类型构造,无需依赖标签匹配 return constructType(resolvedClassByTag, node); } // ... 处理其他类 ... return super.constructObject(node); }
内容的提问来源于stack exchange,提问作者mmo
相关产品推荐
相关产品推荐

