相同Java对象上的不同XML映射/绑定



我有一个Java应用程序,可以与其他几个信息系统互操作

根据信息系统目标,同一对象可以映射到不同的XML文件中

我的问题是:是否有Java解决方案可以在同一对象上执行服务器XML映射/绑定

一些类似于Bean验证组的东西,可以使用不同的验证配置文件验证对象

在JAXB风格中,它可以是类似的东西,例如:

// pseudocode
@XmlRootElement(name="person", , profile="profile1")
@XmlRootElement(name="individual", profile="profile2")
@XmlRootElement(name="human", profile="profile3")
public class Person {
@XmlElement(name = "lastName", profile="profile1")
@XmlElement(name = "surname", profile="profile2")
@XmlElement(name = "famillyName", profile="profile3")
private String lastName;
//...
}

然后

// pseudocode
File file = new File("C:\file.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller("profile1");
jaxbMarshaller.marshal(person, file);
//...
File file = new File("C:\file.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller("profile1");
Person person = (Person) jaxbUnmarshaller.unmarshal(file);

也许可以用JAXB做这样的事情,但我没有找到


编辑

@MartinSerrano的回复为我提供了一些使用JAXB优化事物的线索。

一个抽象类来统治它们:

@XmlTransient
public abstract class APerson {
protected String lastname;
public APerson() {
}
public APerson(APerson p) {
lastname = p.lastname;
}
public abstract String getLastname();
public void setLastname(String lastname) {
this.lastname = lastname;
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{" + lastname + "}";
}
}

具体的类进行映射:

默认映射的类别Person

@XmlRootElement
public class Person extends APerson {
public Person() {
}
public Person(APerson p) {
super(p);
}
@Override
public String getLastname() {
return lastname;
}
}

以及其他用于替代映射的类:

@XmlRootElement
public class Human extends APerson {
public Human() {
}
public Human(APerson p) {
super(p);
}
@Override
@XmlElement(name = "famillyName")
public String getLastname() {
return lastname;
}
}

@XmlRootElement
public class Individual extends APerson{   
public Individual() {
}
public Individual(APerson p) {
super(p);
}    
@Override
@XmlElement(name = "surname")
public String getLastname() {
return lastname;
}
}

测试:

public class Main {
public static void main(String[] args) throws Exception {
Person person = new Person();
person.setLastname("Doe");
String fileName = "person.xml";
marshal(person, fileName);
person = unmarshal(Person.class, fileName);
System.out.println(person);
fileName = "human.xml";
Human human = new Human(person);
marshal(human, fileName);
human = unmarshal(Human.class, fileName);
System.out.println(human);
person = new Person(human);
System.out.println(person);
fileName = "individual.xml";
Individual individual = new Individual(person);
marshal(individual, fileName);
individual = unmarshal(Individual.class, fileName);
System.out.println(individual);
person = new Person(individual);
System.out.println(person);
}
private static <P extends APerson> void marshal(P person, String fileName) throws JAXBException {
File file = new File(fileName);
JAXBContext context = JAXBContext.newInstance(person.getClass());
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(person, file);
marshaller.marshal(person, System.out);
}
private static <P extends APerson> P unmarshal(Class<P> cl, String fileName) throws JAXBException {
File file = new File(fileName);
JAXBContext context = JAXBContext.newInstance(cl);
Unmarshaller unmarshaller = context.createUnmarshaller();
P person = (P) unmarshaller.unmarshal(file);
return person;
}
}

结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person>
<lastname>Doe</lastname>
</person>
Person{Doe}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<human>
<famillyName>Doe</famillyName>
</human>
Human{Doe}
Person{Doe}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<individual>
<surname>Doe</surname>
</individual>
Individual{Doe}
Person{Doe}

这是我发现的最好的解决方案,它具有不同的映射并避免代码重复,所以我们只需要使用映射来实现getter。

让我们看看它是否能解决更大的问题!

但是,尽管它比拥有3个抑制类要好得多,但它仍然不是同一类上的3个映射。。。

这样做的最简单方法是为每个系统使用不同的外观。这将允许您更改JAXB对对象进行反序列化的方式。它还允许您根据所讨论的系统进行其他转换和调整。基本Person类将具有默认的序列化,如果需要,每个系统都可以使用适合它的facade。这基本上是关于映射接口的非官方jaxb指南中概述的方法。

这样的facade可以为每个系统注册,允许您将系统特定的概要文件排除在每个核心类型的代码之外。

使用您的示例,核心接口将是:

@XmlRootElement(name="person")
public interface Person {
@XmlElement(name = "lastName")
private String lastName;
}

那么对于System1,你会有:

@XmlRootElement(name="individual")
public class Individual implements Person {
}

另一个系统可能有:

@XmlRootElement(name="human")
public class Human implements Person {
}

最新更新