使用SnakeYAML序列化YAML时排除disabled为true的对象
问题:如何在SnakeYAML序列化时完全移除disabled为true的Norwich对象
我需要将disabled属性为true的Norwich对象在序列化为YAML时彻底隐藏,但目前的实现只能生成null值或空白节点,无法完全移除这类对象。我参考SnakeYAML文档实现了自定义Representer,但未达到预期效果。
自定义Representer代码
public class MyYamlRepresenter extends Representer { public MyYamlRepresenter() { super(); this.representers.put(Norwich.class,new NorwichRepresenter()); } private class NorwichRepresenter implements Represent { @Override public Node representData(Object o) { Norwich norwich = (Norwich) o; if(norwich.getDisabled()!=null && norwich.getDisabled()){ //return representScalar(Tag.NULL,""); return nullRepresenter.representData((Object) null); } return representJavaBean(getProperties(Norwich.class),norwich); } } // filter null fields and those I don't need @Override protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { if(javaBean==null){ return null; }else if(propertyValue==null){ return null; }else if(propertyValue instanceof List && ((List<?>) propertyValue).size()==0 && !property.getName().equals("children")){ return null; }else if(property.getName().equals("disabled")){ return null; } else{ return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag); } } }
Norwich类定义
public class Norwich{ private String type; private String name; private Integer id; private Integer interval; private Integer count; private Boolean disabled; private List<Integer> conditions = new ArrayList<>(); private Integer condition; // recursive children private List<Norwich> children = new ArrayList<>(); // getters and setters }
序列化代码
DumperOptions options = new DumperOptions(); MyYamlRepresenter myYamlRepresenter = new MyYamlRepresenter(); myYamlRepresenter.addClassTag(foo.bar.NorwichParent.class, Tag.MAP); Yaml yaml=new Yaml(myYamlRepresenter,options); NorwichParent parent = new NorwichParent(); List<Norwich> norwiches = mysql.select();// 从数据库获取数据 parent.setChildren(norwiches); yaml.dump(parent,fileWriter);
当前生成的YAML(存在null节点)
type: main name: main id: 1 children: - null - type: logic_if name: if id: 5 condition: 1 children: - type: logic_if_true name: true id: 6 children: [null] - type: logic_if_false name: false id: 7 children: []
期望的干净YAML
type: main name: main id: 1 children: - type: logic_if name: if id: 5 condition: 1 children: - type: logic_if_true name: true id: 6 children: [] - type: logic_if_false name: false id: 7 children: []
解决方案
核心问题是:当前仅将disabled的Norwich转为null节点,但SnakeYAML处理列表时不会自动过滤null元素。需要在处理列表属性时,提前过滤掉disabled为true的Norwich对象,从根源避免null节点生成。
修改后的自定义Representer代码如下:
public class MyYamlRepresenter extends Representer { public MyYamlRepresenter() { super(); this.representers.put(Norwich.class, new NorwichRepresenter()); } private class NorwichRepresenter implements Represent { @Override public Node representData(Object o) { Norwich norwich = (Norwich) o; if (norwich.getDisabled() != null && norwich.getDisabled()) { // 直接返回null,后续列表过滤会移除这类节点 return nullRepresenter.representData(null); } return representJavaBean(getProperties(Norwich.class), norwich); } } @Override protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) { if (javaBean == null) { return null; } // 处理List类型,过滤掉disabled为true的Norwich对象 if (propertyValue instanceof List) { List<?> originalList = (List<?>) propertyValue; List<Object> filteredList = new ArrayList<>(); for (Object item : originalList) { if (item instanceof Norwich) { Norwich norwich = (Norwich) item; // 过滤disabled为true的对象 if (!(norwich.getDisabled() != null && norwich.getDisabled())) { filteredList.add(item); } } else { // 非Norwich类型的元素直接保留 filteredList.add(item); } } // 替换原列表为过滤后的列表 propertyValue = filteredList; } // 原有过滤逻辑 if (propertyValue == null) { return null; } else if (propertyValue instanceof List && ((List<?>) propertyValue).size() == 0 && !property.getName().equals("children")) { return null; } else if (property.getName().equals("disabled")) { return null; } return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag); } }
关键修改说明
- 在
representJavaBeanProperty方法中,新增列表过滤逻辑:遍历List中的元素,若为Norwich对象则检查disabled属性,仅保留disabled不为true的元素; - 替换原列表为过滤后的列表,这样后续序列化时就不会包含需要隐藏的对象,自然不会生成null节点;
- 原有单个Norwich对象的处理逻辑保留,作为双重保障,防止漏网的disabled对象被序列化为null。
使用修改后的Representer进行序列化,即可得到无null节点的干净YAML。
内容的提问来源于stack exchange,提问作者Zhiqiang Guo
相关产品推荐
相关产品推荐

