【问题标题】:How to marshall an objectgraph with Java XML binding to a specific depth?如何将具有 Java XML 绑定的对象图编组到特定深度?
【发布时间】:2011-05-13 07:27:50
【问题描述】:

作为 Java XML 绑定的新手,我面临着挑战。

假设我有一个构建域模型的场景,我想将此域编组为 xml 结构。

现在我想提供不同的解组路径:

  1. Marshall 整个对象图 [这里没问题]
  2. 将对象图编组到特定深度!!! [挑战]

如果不引入太多复杂性,我无法找到解决此问题的好方法。可以复制域并在以后手动复制,但这感觉不对。还有其他可用的解决方案吗?

【问题讨论】:

    标签: java xml data-binding jaxb jibx


    【解决方案1】:

    您可以利用 XmlAdapter 和 Marshal.Listener 来获得这种行为:

    演示

    将设置 Marshal.Listener 来跟踪我们正在编组的树的深度。我们还将设置知道深度侦听器的运行时级别 XmlAdapter。当达到所需深度时,这些适配器将开始返回 null。

    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.Marshaller;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Root.class);
    
            Root rootA = new Root();
            rootA.setName("A");
    
            Root rootB = new Root();
            rootB.setName("B");
            rootA.setChild(rootB);
    
            Root rootC = new Root();
            rootC.setName("C");
            rootB.setChild(rootC);
    
            Root rootD = new Root();
            rootD.setName("D");
            rootC.setChild(rootD);
    
            Root rootE = new Root();
            rootE.setName("E");
            rootD.setChild(rootE);
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    
            DepthListener depthListener = new DepthListener(3);
            marshaller.setListener(depthListener);
            marshaller.setAdapter(new RootAdapter(depthListener));
            marshaller.marshal(rootA, System.out);
        }
    
    }
    

    深度监听器

    这个类的目的是跟踪当前的深度。

    import javax.xml.bind.Marshaller;
    
    public class DepthListener extends Marshaller.Listener {
    
        private int targetDepth;
        private int currentDepth = 0;
    
        public DepthListener(int depth) {
            this.targetDepth = depth;
        }
    
        @Override
        public void beforeMarshal(Object source) {
            currentDepth++;
        }
    
        @Override
        public void afterMarshal(Object source) {
            currentDepth--;
        }
    
        public boolean isMarshalDepth() {
            return currentDepth <= targetDepth; 
        }
    
    }
    

    根适配器

    XmlAdapter 的目的是在达到所需深度时开始返回 null 以停止编组过程。

    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class RootAdapter extends XmlAdapter<Root, Root> {
    
        private DepthListener depthListener;
    
        public RootAdapter() {
        }
    
        public RootAdapter(DepthListener depthListener) {
            this.depthListener = depthListener;
        }
    
        @Override
        public Root unmarshal(Root root) throws Exception {
            return root;
        }
    
        @Override
        public Root marshal(Root root) throws Exception {
            if(depthListener != null && !depthListener.isMarshalDepth()) {
                return null;
            }
            return root;
        }
    
    }
    

    下面演示了如何通过@XmlJavaTypeAdapter注解在域对象上指定XmlAdapter:

    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.XmlType;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    @XmlRootElement
    @XmlJavaTypeAdapter(RootAdapter.class)
    @XmlType(propOrder={"name", "child"})
    public class Root {
    
        private String name;
        private Root child;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Root getChild() {
            return child;
        }
    
        public void setChild(Root report) {
            this.child = report;
        }
    
    }
    

    输出

    以下是演示代码的输出:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <root>
        <name>A</name>
        <child>
            <name>B</name>
            <child>
                <name>C</name>
            </child>
        </child>
    </root>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多