1

我有一个现有的复杂对象模型,我试图将其编组为 JAXB xml。如果可能,我不想更改任何现有的域类。我有这个片段可以编组到一个文件(使用 Groovy)

def marshallToFile(Object objectToMarshall, File location){

    def context = JAXBContext.newInstance(objectToMarshall.class)

    def m = context.createMarshaller()
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true)

    location.withOutputStream { out ->
        m.marshal(new JAXBElement(new QName("","rootTag"),objectToMarshall.class,objectToMarshall), out)
    }

}

问题是对象图非常复杂,JAXB 告诉我com.sun.istack.internal.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML: com.example.Object@1eef1eb[Id=100053900] -> com.example.Object@1eef1eb[Id=100053900]

有什么方法可以获取有关检测到的周期的更多信息?有谁知道可以帮助分析图表或以图形方式列出图表以便我挑选周期的工具?我感觉这张图中有很多周期(它既古老又复杂),因此我们将不胜感激。

也许作为替代方案,您能否告诉 JAXB 只深入“n”级或类似的东西,这样它就不会创建无限深的 XML?

编辑:

所以关于我的具体问题......原来现有的域对象定义了一个Object getThis()void setThis(Object obj)方法,即“获取”和“设置”this自引用关键字。这就是导致我循环的原因。这也突出了这样一个事实,即 JAXB 必须使用 JavaBean 方法定义来确定它将编组哪些属性(我以前不知道)。

但是,我认为最初的问题仍然存在,是否有任何好的工具可以分析/查看对象图?

4

2 回答 2

2

也许您可以引入一个Marshaller.Listener来跟踪编组过程并转储对象信息,以进行诊断。有关详细信息,请参阅“Marshal Event Callbacks”(引用“外部侦听器”的部分)。这不应该需要更改您现有的域。

于 2013-01-11T15:33:10.927 回答
0

您可以让您的对象实现CycleRecoverable接口以查找有关循环的信息。

import java.util.*;
import javax.xml.bind.annotation.*;
import com.sun.xml.bind.CycleRecoverable;

@XmlRootElement
public class Department implements CycleRecoverable {

   @XmlAttribute
   public int id;
   public String name;
   public List<Employee> employees = new ArrayList<Employee>();

   public Object onCycleDetected(Context arg0) {
       // Context provides access to the Marshaller being used:
       System.out.println("JAXB Marshaller is: " + cycleRecoveryContext.getMarshaller());

       DepartmentPointer p = new DepartmentPointer();
       p.id = this.id;
       return p;
   }

}

了解更多信息

于 2013-01-11T15:25:56.707 回答