Как сериализовать и десериализовать объекты, используя JAXB? - PullRequest
36 голосов
/ 04 марта 2011

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

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

Ответы [ 3 ]

40 голосов
/ 04 марта 2011

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

Примечание:

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

}
37 голосов
/ 04 марта 2011

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

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

2 голосов
/ 04 марта 2011

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...