Java 如何使用JAXB序列化和反序列化对象?

Java 如何使用JAXB序列化和反序列化对象?,java,jaxb,Java,Jaxb,我有个问题。我想使用JAXB将一个对象转换成另一个对象。就像在中一样,我有一个类com.home.Student,另一个类com.school.Student,它们都有相同的参数,实际上都是相同的(复制粘贴),但包不同。我想使用JAXB执行它们之间的转换 如何做到这一点,请帮助我。如果您能提供一些代码来解释您的问题,那就太好了 JAXB 101说应该放置正确的注释,然后才能正确地序列化和反序列化。你应该用、、等正确地注释你的类 例如: @XmlRootElement(name="student"

我有个问题。我想使用JAXB将一个对象转换成另一个对象。就像在中一样,我有一个类
com.home.Student
,另一个类
com.school.Student
,它们都有相同的参数,实际上都是相同的(复制粘贴),但包不同。我想使用
JAXB
执行它们之间的转换


如何做到这一点,请帮助我。

如果您能提供一些代码来解释您的问题,那就太好了

JAXB 101说应该放置正确的注释,然后才能正确地序列化和反序列化。你应该用、、等正确地注释你的类

例如:

@XmlRootElement(name="student")
@XmlAccessorType(XmlAccessType.NONE)
class Student {
  @XmlElement(name="name")
  private String name;

  @XmlElement(name="age")
  private int age;

  public Student() {
  }

  public String getName() { return name; }

  public int getAge() { return age; }
}
然后可以使用JAXB对其进行序列化:

并通过输入对其进行反序列化

JAXBContext context = JAXBContext.newInstance(Student.class);
Unmarshaller m = context.createUnmarshaller();
return (Student)m.unmarshal(new StringReader(input));
请务必查看我上面提到的JavaDoc,因为有很多方法可以做到这一点

如果您无法修改类,则仍然可以使用JAXB(或者可以使用XStream),前提是您的类如下所示:

class Student {
  private String name;
  private int age;

  public Student() {
  }

  public void setName(String name) { this.name = name; }
  public String getName() { return name; }
  public void setAge(int age) { this.age = age; }
  public int getAge() { return age; }
}
您可以通过执行以下操作将其序列化:

Student student = new Student();
student.setAge(25);
student.setName('FooBar');
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(Student.class);
Marshaller m = context.createMarshaller();
m.marshal(new JAXBElement(new QName(Student.class.getSimpleName()), Student.class, student), writer);
System.out.println(writer.toString());
如果您正在使用,那么您也可以在没有注释的情况下进行序列化(而且它更易于控制)。
您可以执行以下操作

注意:

  • 它不需要通过利用JAXBSource将数据具体化为XML
  • 它不需要在对象模型上添加任何注释
com.home.Student

package com.home;

public class Student {

    private String name;
    private Status status;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

}
package com.school;

public class Student {

    private String name;
    private Status status;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

}
com.home.Status

package com.home;

public enum Status {

    FULL_TIME("F"),
    PART_TIME("P");

    private final String code;

    Status(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

}
package com.school;

public enum Status {

    FULL_TIME("F"),
    PART_TIME("P");

    private final String code;

    Status(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

}
com.school.Student

package com.home;

public class Student {

    private String name;
    private Status status;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

}
package com.school;

public class Student {

    private String name;
    private Status status;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

}
com.school.Status

package com.home;

public enum Status {

    FULL_TIME("F"),
    PART_TIME("P");

    private final String code;

    Status(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

}
package com.school;

public enum Status {

    FULL_TIME("F"),
    PART_TIME("P");

    private final String code;

    Status(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }

}
com.example.Demo

package com.example;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.util.JAXBSource;
import javax.xml.namespace.QName;

public class Demo {

    public static void main(String[] args) throws Exception {
        com.home.Student studentA = new com.home.Student();
        studentA.setName("Jane Doe");
        studentA.setStatus(com.home.Status.FULL_TIME);

        JAXBContext contextA = JAXBContext.newInstance(com.home.Student.class);
        JAXBElement<com.home.Student> jaxbElementA = new JAXBElement(new QName("student"), com.home.Student.class, studentA);
        JAXBSource sourceA = new JAXBSource(contextA, jaxbElementA);

        JAXBContext contextB = JAXBContext.newInstance(com.school.Student.class);
        Unmarshaller unmarshallerB = contextB.createUnmarshaller();
        JAXBElement<com.school.Student> jaxbElementB = unmarshallerB.unmarshal(sourceA, com.school.Student.class);

        com.school.Student studentB = jaxbElementB.getValue();
        System.out.println(studentB.getName());
        System.out.println(studentB.getStatus().getCode());
    }

}
package.com.example;
导入javax.xml.bind.JAXBContext;
导入javax.xml.bind.JAXBElement;
导入javax.xml.bind.Unmarshaller;
导入javax.xml.bind.util.JAXBSource;
导入javax.xml.namespace.QName;
公开课演示{
公共静态void main(字符串[]args)引发异常{
com.home.Student studentA=新的com.home.Student();
学生姓名(“简·多伊”);
学生状态(com.home.Status.全职);
JAXBContext contextA=JAXBContext.newInstance(com.home.Student.class);
JAXBElement-jaxbElementA=new-JAXBElement(new-QName(“学生”),com.home.student.class,studentA);
JAXBSource sourceA=新的JAXBSource(contextA,jaxbElementA);
JAXBContext contextB=JAXBContext.newInstance(com.school.Student.class);
Unmarshaller unmarshallerB=contextB.createUnmarshaller();
JAXBElement jaxbElementB=unmarshallerB.unmarshal(sourceA,com.school.Student.class);
com.school.studentB=jaxbElementB.getValue();
System.out.println(studentB.getName());
System.out.println(studentB.getStatus().getCode());
}
}

如果您的目标只是在两者之间进行转换(实际分配),并且它们除了包名之外是相同的,那么我认为您可以使用简单反射。只需迭代源对象的字段,并将其指定给目标对象中同名的字段。模糊地,像这样:

import java.lang.reflect.Field;

public class Converter {
    public void convert (com.home.Student src, com.school.Student dst) throws Exception {
        for (Field f : src.getFields()) {

            // src field name
            String name = f.getName();

            // get corresponding field in dst
            Field dstField = dst.getDeclaredField(name);

            dstField.set(dst, f.get());
        }
    }
}

注意:我没有编译这个,这就是为什么我说“模糊”。如果字段是私有的,则需要使用Field.isAccessible()/Field.setAccessible(true),以便在赋值时临时更改可访问性。或者,您可以编写一个稍微复杂一些的代码,使用公共setter/getter,而不是直接使用字段访问。

hi,上面的实现方法非常好,我需要知道,如果不添加这些@tags,上面的代码将无法工作???我的意思是除此之外,还有别的办法吗你说它不起作用是什么意思?确保您使用的是JDK 6。好吧,我打开了VIM并使用了我上面演示的内容,它工作得很好:它已经工作了。。而且没有任何错误。基本上,我想知道是否还有其他方法可以这样做,因为我无法更改类。那么,如果您不使用注释,您可以告诉它元素使用的是什么QName:
m.marshal(新的JAXBElement(新的QName(Student.class.getSimpleName()),Student.class,Student),writer)如果没有注释,我会更新代码。关于XStream,请检查:这很好,我不知道JAXBSource在同一个应用程序中序列化/反序列化时非常有用。谢谢:)@blaise:我想我不适用于枚举,如果对象有枚举,那么它说没有定义默认构造函数就失败了。@Mrityunjay-枚举属性也应该可以工作,我已经更新了我的答案以包含一个枚举。@blaise:使用此枚举,此代码可以工作,但是假设你有一个类似Stutus的枚举,它的值是PART_TIME(“P”)、FULL_TIME(“F”),对于这种类型的枚举,转换失败,因为枚举失败,表示找不到默认构造函数,因为为了编译枚举,我们需要放置一个参数化构造函数。你说得对,我使用的是另一个版本。因此,您的解决方案很酷,谢谢。这是一种更好的方法,但是我们可以编写一些通用代码,这些代码可以跨对象使用,因为我的需求不是针对一个对象,而是针对多个对象,所以一遍又一遍地编写相同的代码,对于所有对象都不是一件好事,这是我想到JAXB的唯一原因。