Как сериализовать и десериализовать объекты, используя JAXB?

У меня есть проблема. Я хочу преобразовать объект в другой объект, используя JAXB. Как и у меня есть класс com.home.Studentи другой класс com.school.Student, оба имеют одинаковые аргументы, на самом деле оба одинаковы (копировать, вставить), но разные пакеты. Я хочу выполнить преобразование между ними, используя JAXB,

Как это сделать, пожалуйста, помогите мне.

3 ответа

Решение

Вы могли бы сделать следующее.

Замечания:

  • Это не требует, чтобы вы когда-либо материализовали данные как XML, используя JAXBSource.
  • Он не требует каких-либо аннотаций на вашей объектной модели.

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;
    }

}

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;
    }

}

com.school.Student

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.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());
    }

}

Было бы неплохо, если бы вы включили код, объясняющий вашу проблему.

JAXB 101 говорит, что вы должны разместить правильные аннотации, тогда вы сможете правильно сериализовать и десериализовать. Вы должны правильно аннотировать свои классы с помощью @XmlRootElement, @XmlElement, @XmlAttribute и т. Д.

Например:

@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 Marshaller:

StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(Student.class);
Marshaller m = context.createMarshaller();
m.marshal(student, writer);

И десериализовать это также, Unmarshelling вход..

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());

Если вы используете XStream, вы можете выполнять сериализацию без аннотаций (и это более управляемо). http://x-stream.github.io/tutorial.html

Если ваша цель - просто преобразовать (назначить) между ними, и они идентичны, кроме имени пакета, я думаю, вы могли бы использовать простое отражение. Просто переберите поля исходного объекта и присвойте полю с тем же именем в целевом объекте. Смутно, вот так:

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), если поля являются закрытыми, чтобы вы могли временно изменить доступность при назначении значений. Или вы пишете немного более сложный код, который использует общедоступные установщики / получатели, а не напрямую, используя полевой доступ.

Другие вопросы по тегам