Filter a list before serialization using SimpleXml

 ̄綄美尐妖づ 提交于 2019-12-07 22:05:06

问题


I am trying to serialize a parent which contains a list of childs. These childs have an activated boolean field, and I want that the resulting XML contains only the childs wich an activated attribute set to true

I could do this by copying the parent object and filtering the childs in the process (and I may do this at the end) but I am wondering if it is possible to customize SimpleXML to have the same result.

EDIT

I used the response given by ollo. I just changed the Converter implementation for using the original annotations of the child classes.

The new Converter implementation:

public class ChildConverter implements Converter<Child>
{
    @Override
    public Child read(InputNode node) throws Exception
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }


    @Override
    public void write(OutputNode node, Child value) throws Exception
    {
        if( value.isActived() == true ) // Check if 'activated' flag is set
        {
            // Set valus of the child
            //We don't use an annotation strategy for this persister to avoid
            //a recursive call to this method.
            Serializer serializer = new Persister();
            serializer.write(value, node);
        }
        else
        {
            node.remove(); // Remove the node since we don't need it
        }
    }

}

回答1:


Some more informations (code, expected XML etc.) would be helpful ...

But here's an example how you can do this:

The key feature is implementing a Converter, where you can customize how objects are serialized / deserialized. In the following code I implement a Converter for the Child class, however it's possible to implement it for the Parent class instead too.

The Child class:

@Root(name = "child")
@Convert(value = ChildConverter.class) // Set the Converter
public class Child
{
    private boolean actived;
    @Element(name = "value", required = true)
    private String value;
    @Element(name = "value2", required = true)
    private int secondValue;


    public Child(boolean actived, String value, int secondValue)
    {
        this.actived = actived;
        this.value = value;
        this.secondValue = secondValue;
    }



    public boolean isActived()
    {
        return actived;
    }

    public String getValue()
    {
        return value;
    }

    public int getSecondValue()
    {
        return secondValue;
    }

    // ...
}

Beside the activated flag this class has two other members to show how do serialize them.

The Parent class:

@Root(name = "parent")
public class Parent
{
    @ElementList(name = "childs", required = true)
    private List<Child> childs;


    public Parent()
    {
        this.childs = new ArrayList<>();
    }



    public void addChild(Child child)
    {
        childs.add(child);
    }

    // ...
}

The Converter implementation:

public class ChildConverter implements Converter<Child>
{
    @Override
    public Child read(InputNode node) throws Exception
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }


    @Override
    public void write(OutputNode node, Child value) throws Exception
    {
        if( value.isActived() == true ) // Check if 'activated' flag is set
        {
            // Set valus of the child
            node.setValue(value.getValue());
            node.setAttribute("secondValue", String.valueOf(value.getSecondValue()));
        }
        else
        {
            node.remove(); // Remove the node since we don't need it
        }
    }

}

The implementation is not very complex so far. First we check if activated is set. If yes we fill the objects value into the node, if it's not set we remove the node (else you'll get a <child /> in your XML).

How to use:

// Some test data
Parent p = new Parent();
p.addChild(new Child(true, "a", 1));
p.addChild(new Child(true, "b", 2));
p.addChild(new Child(false, "c", 3)); // "disabled"
p.addChild(new Child(true, "d", 4));
p.addChild(new Child(false, "e", 5)); // "disabled"
p.addChild(new Child(false, "f", 6)); // "disabled"


final File f = new File("test.xml");

Serializer ser = new Persister(new AnnotationStrategy()); // Don't forget 'AnnotationStrategy'!
ser.write(p, f); // Serialize to a file or whatever you need

And finally ...

The XML output:

<parent>
   <childs class="java.util.ArrayList">
      <child secondValue="1">a</child>
      <child secondValue="2">b</child>
      <child secondValue="4">d</child>
   </childs>
</parent>

There are only child elements for object where activated was true, those with false are skipped.

Note: If you want to remove class="java.util.ArrayList" please see here: Remove class= attribute



来源:https://stackoverflow.com/questions/17021119/filter-a-list-before-serialization-using-simplexml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!