Подтвердить что ты не робот

Как сериализовать и де-сериализовать объекты с помощью JAXB?

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

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

4b9b3361

Ответ 1

Вы можете сделать следующее.

Примечание:

  • Это не требует, чтобы вы когда-либо материализовали данные как 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());
    }

}

Ответ 2

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

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

Ответ 3

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

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