Java JAXB未解组子对象@XmlIDREF

Java JAXB未解组子对象@XmlIDREF,java,jaxb,unmarshalling,Java,Jaxb,Unmarshalling,我有一个对象(A),它具有另一个对象(B)的属性。编组对象A时,我存储对对象B的引用。B中的ID本身就是一个对象(Mongo ObjectId)。我将MongoId对象包装在一个XmlAdapter中,并通过@XmlIDREF引用对象B。编组工作很棒。解组丢失了对象B。我确信我丢失了一些东西,因为我希望解组将等效对象返回到最初编组的对象 下面是一个简单的例子,其中一个学生提到了他的老师。有人能解释为什么(或者给我指一些文档)教师对象没有被解包吗 谢谢 import javax.xml.bind.

我有一个对象(A),它具有另一个对象(B)的属性。编组对象A时,我存储对对象B的引用。B中的ID本身就是一个对象(Mongo ObjectId)。我将MongoId对象包装在一个XmlAdapter中,并通过@XmlIDREF引用对象B。编组工作很棒。解组丢失了对象B。我确信我丢失了一些东西,因为我希望解组将等效对象返回到最初编组的对象

下面是一个简单的例子,其中一个学生提到了他的老师。有人能解释为什么(或者给我指一些文档)教师对象没有被解包吗

谢谢

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.StringWriter;
import java.io.ByteArrayInputStream;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

// Can't change anything in this example class; it is part of an external library
class MongoID {
    private String id;

    public MongoID(){};

    public MongoID(String id) { this.id = id; }

    public String toString() { return this.id; }
}

// wrap any marshalling/unmarshalling of MongoID objects to get to/from a string
class IDAdaptor extends XmlAdapter<String, MongoID>
{
    @Override
    public MongoID unmarshal( String id ) {         
        return new MongoID(id);
    }

    @Override
    public String marshal( MongoID id ) {
        return id.toString();
    }
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Teacher {

    @XmlID
    @XmlJavaTypeAdapter(IDAdaptor.class)
    private MongoID id;

    public Teacher() {}

    public Teacher(String a) {
        this.id = new MongoID(a);
    }

    public MongoID getId() { return this.id; }

    public void setId(MongoID id) { this.id = id; }
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Student {

    @XmlIDREF
    private Teacher teacher;

    public Teacher getTeacher() { return this.teacher; }

    public void setTeacher(Teacher teacher) { this.teacher = teacher; }

    public void setTeacher(String id) { System.out.println("!!!!"); }
}

class TeacherTest {
    public static String marshall(Object object) throws javax.xml.bind.JAXBException {
        JAXBContext context = JAXBContext.newInstance(object.getClass());
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        StringWriter writer = new StringWriter();
        marshaller.marshal(object, writer);

        return writer.toString();
    }

    public static Object unmarshall(String xml, Class[] domType ) throws javax.xml.bind.JAXBException {
        JAXBContext context = JAXBContext.newInstance(domType);
        Unmarshaller unmarshaller = context.createUnmarshaller();

        ByteArrayInputStream input = new ByteArrayInputStream(xml.getBytes());
        return unmarshaller.unmarshal(input);
    }

    public static void main(String[] args) {
        try {
            Teacher teacher = new Teacher();
            teacher.setId(new MongoID("52e3d51c44ae1b9d39ef5827"));

            Student student = new Student();
            student.setTeacher(teacher);

            String output = marshall(student);

            System.out.println(output);

            Class[] classes = new Class[]{Teacher.class, Student.class};
            Student student2 = (Student) unmarshall(output, classes);

            output = marshall(student2);
            System.out.println(output);
        }
        catch ( Exception e ) {
            e.printStackTrace();
        }       
    }
}
import javax.xml.bind.JAXBContext;
导入javax.xml.bind.JAXBException;
导入javax.xml.bind.Marshaller;
导入javax.xml.bind.Unmarshaller;
导入java.io.StringWriter;
导入java.io.ByteArrayInputStream;
导入javax.xml.bind.annotation.*;
导入javax.xml.bind.annotation.adapters.XmlAdapter;
导入javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
//无法更改此示例类中的任何内容;它是外部库的一部分
类MongoID{
私有字符串id;
公共MongoID(){};
公共MongoID(字符串id){this.id=id;}
公共字符串toString(){返回this.id;}
}
//包装MongoID对象的任何编组/解编组,以访问字符串
类IDAdaptor扩展了XmlAdapter
{
@凌驾
公共MongoID解组(字符串id){
返回新的MongoID(id);
}
@凌驾
公共字符串封送处理(MongoID){
返回id.toString();
}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
班主任{
@XmlID
@XmlJavaTypeAdapter(IDAdaptor.class)
私有MongoID;
公共教师(){}
公立教师(a字串){
this.id=新的MongoID(a);
}
public MongoID getId(){返回this.id;}
public void setId(MongoID id){this.id=id;}
}
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
班级学生{
@XmlIDREF
私人教师;
公共教师getTeacher(){返回this.Teacher;}
公共无效设置器(教师){this.Teacher=Teacher;}
public void settacher(字符串id){System.out.println(“!!!!”);}
}
班主任考试{
公共静态字符串marshall(对象对象)抛出javax.xml.bind.JAXBException{
JAXBContext context=JAXBContext.newInstance(object.getClass());
Marshaller=context.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,true);
StringWriter编写器=新的StringWriter();
marshaller.marshall(对象、编写器);
返回writer.toString();
}
公共静态对象解组(字符串xml,类[]domType)抛出javax.xml.bind.JAXBException{
JAXBContext context=JAXBContext.newInstance(domType);
Unmarshaller Unmarshaller=context.createUnmarshaller();
ByteArrayInputStream输入=新建ByteArrayInputStream(xml.getBytes());
返回unmarshaller.unmarshal(输入);
}
公共静态void main(字符串[]args){
试一试{
教师=新教师();
setId(新MongoID(“52e3d51c44ae1b9d39ef5827”);
学生=新生();
学生、教师;
字符串输出=马歇尔(学生);
系统输出打印项次(输出);
班级[]班级=新班级[]{Teacher.Class,Student.Class};
学生2=(学生)解组(输出,班级);
输出=马歇尔(学生2);
系统输出打印项次(输出);
}
捕获(例外e){
e、 printStackTrace();
}       
}
}
运行上面的示例会在编组后生成此XML

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student>
    <teacher>52e3d51c44ae1b9d39ef5827</teacher>
</student>

52e3d51c44ae1b9d39ef5827
然后解组,然后是马歇尔:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<student/>

一个
IDREF
是一个指向XML文档中具有相应
ID
的内容的指针。您需要确保您引用的内容也在文档中


是的,谢谢,我读了你的博客文章和其他资料,但我认为JAXB的工作原理与我在其他语言中使用的XML序列化器/反序列化器相同,在其他语言中,您可以获得与放入相同的对象。JAXB不是这样工作的。