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

使用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);
    }
}

关键修改说明

  1. 在representJavaBeanProperty方法中,新增列表过滤逻辑:遍历List中的元素,若为Norwich对象则检查disabled属性,仅保留disabled不为true的元素;
  2. 替换原列表为过滤后的列表,这样后续序列化时就不会包含需要隐藏的对象,自然不会生成null节点;
  3. 原有单个Norwich对象的处理逻辑保留,作为双重保障,防止漏网的disabled对象被序列化为null。

使用修改后的Representer进行序列化,即可得到无null节点的干净YAML。


内容的提问来源于stack exchange,提问作者Zhiqiang Guo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 11:04:56