Search code examples
javasnakeyaml

Exclude whole object when dumping yaml using snakeyaml


I want to make objects invisible whose disabled are true when serializing them to the yaml,but I can't remove them but get some nulls.

I construct my own Representer after reading docs of snake:

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

and class 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
}

Then I tried to dump another object who keeps a list of Norwich as its children:

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();// I got them from database
parent.setChildren(norwiches);
yaml.dump(parent,fileWriter);

Then I got a file like this:

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: []

and I switch the comment in MyYamlRepresenter which using representScalar instead, the result just changed to:

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: [!!null '']
  - type: logic_if_false
    name: false
    id: 7
    children: []

So how do I just skip the whole obj and remove the first child of main and the first child of {id:6}:

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: []

Solution

  • Thanks to @Alex R.

    public MyYamlRepresenter() {
        super();
    // remember comment this out, in case of NullPointerException: null.getDisabled();
    //  this.representers.put(Norwich.class,new NorwichRepresenter());
    
        // concrete class ArrayList rather List
        this.representers.put(ArrayList.class,new ListRepresenter());
    }
    private class ListRepresenter implements Represent{
      @Override
      public Node representData(Object o) {
        List<Norwich> newList = (List<Norwich>)o;
        List<Norwich> enabled = newList.stream().filter(pre -> pre.getDisabled() == null || !pre.getDisabled()).collect(Collectors.toList());
        return representSequence(getTag(enabled.getClass(), Tag.SEQ), enabled, DumperOptions.FlowStyle.AUTO);
      }
    }
    

    Thanks again.