I need to marshall and unmarshall a Java class to XML. The class in not owned by me, that I cannot add anotations so that I can use JAXB.
我需要将Java类编组并解组为XML。该类不属于我,我无法添加anotations以便我可以使用JAXB。
Is there a good way to convert the Java to XML with the given contraint?
有没有一种很好的方法将Java转换为具有给定约束的XML?
Also, thought a tool may be helpful, but I would be more intersted it there is some Java API to do the same.
此外,认为一个工具可能会有所帮助,但我会更有兴趣它有一些Java API来做同样的事情。
4 个解决方案
#1
16
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
注意:我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员。
DOMAIN MODEL
域模型
I will use the following domain model for this answer. Note how there are no JAXB annotations on the model.
我将使用以下域模型来获得此答案。请注意模型上没有JAXB注释。
Customer
顾客
package forum11693552;
import java.util.*;
public class Customer {
private String firstName;
private String lastName;
private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
}
PhoneNumber
电话号码
package forum11693552;
public class PhoneNumber {
private String type;
private String number;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
OPTION #1 - Any JAXB (JSR-222) Implementation
选项#1 - 任何JAXB(JSR-222)实现
JAXB is configurartion by exception, this means you only need to add annotations where you want the mapping behaviour to differ from the default. Below is a link to an example demonstrating how to use any JAXB impl without annotations:
JAXB是异常配置,这意味着您只需要在希望映射行为与默认值不同的地方添加注释。下面是一个示例的链接,演示如何在没有注释的情况下使用任何JAXB impl:
Demo
演示
package forum11693552;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Customer customer = new Customer();
customer.setFirstName("Jane");
customer.setLastName("Doe");
PhoneNumber workPhone = new PhoneNumber();
workPhone.setType("work");
workPhone.setNumber("555-1111");
customer.getPhoneNumbers().add(workPhone);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
JAXBElement<Customer> rootElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer);
marshaller.marshal(rootElement, System.out);
}
}
Output
产量
<customer>
<firstName>Jane</firstName>
<lastName>Doe</lastName>
<phoneNumbers>
<number>555-1111</number>
<type>work</type>
</phoneNumbers>
</customer>
For More Information
了解更多信息
- http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics
- http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics
OPTION #2 - EclipseLink JAXB (MOXy)'s External Mapping Document
选项#2 - EclipseLink JAXB(MOXy)的外部映射文档
If you do want to customize the mappings, then you may be interested in MOXy's external mapping document extension. A sample mapping document looks like the following:
如果您确实想要自定义映射,那么您可能对MOXy的外部映射文档扩展感兴趣。示例映射文档如下所示:
oxm.xml
oxm.xml
<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum11693552">
<java-types>
<java-type name="Customer">
<xml-root-element />
<java-attributes>
<xml-element java-attribute="firstName" name="first-name" />
<xml-element java-attribute="lastName" name="last-name" />
<xml-element java-attribute="phoneNumbers" name="phone-number" />
</java-attributes>
</java-type>
<java-type name="PhoneNumber">
<java-attributes>
<xml-attribute java-attribute="type" />
<xml-value java-attribute="number" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
jaxb.properties
jaxb.properties
To enable MOXy as your JAXB provider you need to include a file called jaxb.properties
in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):
要将MOXy作为JAXB提供程序启用,您需要在与域模型相同的程序包中包含一个名为jaxb.properties的文件,并带有以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink- MOXY-AS-your.html):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
演示
When using EclipseLink MOXy as your JAXB provider (see), you can leverage the external mapping document when you bootstrap your JAXBContext
使用EclipseLink MOXy作为JAXB提供程序(请参阅参考资料)时,可以在引导JAXBContext时利用外部映射文档
package forum11693552;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String,Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum11693552/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, properties);
Customer customer = new Customer();
customer.setFirstName("Jane");
customer.setLastName("Doe");
PhoneNumber workPhone = new PhoneNumber();
workPhone.setType("work");
workPhone.setNumber("555-1111");
customer.getPhoneNumbers().add(workPhone);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
JAXBElement<Customer> rootElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer);
marshaller.marshal(rootElement, System.out);
}
}
Output
产量
<?xml version="1.0" encoding="UTF-8"?>
<customer>
<first-name>Jane</first-name>
<last-name>Doe</last-name>
<phone-number type="work">555-1111</phone-number>
</customer>
For More Information
了解更多信息
- http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
- http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
- http://blog.bdoughan.com/2012/04/extending-jaxb-representing-metadata-as.html
- http://blog.bdoughan.com/2012/04/extending-jaxb-representing-metadata-as.html
#2
5
Have you looked at XStream ? It will deserialise/deserialise a standard POJO without annotations or XSDs. You can provide customisations to affect how elements appear in the XML and pretty much works out-of-the-box.
你看过XStream吗?它将对没有注释或XSD的标准POJO进行反序列化/反序列化。您可以提供自定义以影响元素在XML中的显示方式,并且几乎可以开箱即用。
#3
1
You could write a custom XmlAdapter
and annotate fields of the constrained type with a XmlJavaTypeAdapter
annotation. The basics would be something like this:
您可以使用XmlJavaTypeAdapter批注编写自定义XmlAdapter并注释约束类型的字段。基础知识将是这样的:
public enum CannotBeAnnotated { value1, value2; }
@XmlRootElement(name="client")
public class ClientClass {
@XmlJavaTypeAdapter(Bridge.class)
public CannotBeAnnotated;
}
@XmlRootElement(name="representation")
public class XmlType {
@XmlValue
public String value;
}
public class Bridge extends XmlAdapter<XmlType, CannotBeAnnotated>{
public XmlType marshal(CannotBeAnnotated c) {
XmlType x=new XmlType();
x.value=c.name();
return x;
}
public CannotBeAnnotated unmarshall(XmlType x) {
return CannotBeAnnotated.valueOf(x.value);
}
}
Of course for enums this would not be useful as JAXB knows how to deal with them. I just picked an enum for simplicity so you can see the idea:
当然,对于枚举,这不会有用,因为JAXB知道如何处理它们。我刚刚选择了一个简单的枚举,所以你可以看到这个想法:
- Design an XML representation that you do control
- 设计您可以控制的XML表示
- Write an adapter converting that Java type into the desired type
- 编写将该Java类型转换为所需类型的适配器
- Annotate "client" code referencing the adapter for the desired type
- 注释引用所需类型的适配器的“客户端”代码
- Profit.
- 利润。
#1
16
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
注意:我是EclipseLink JAXB(MOXy)的负责人,也是JAXB(JSR-222)专家组的成员。
DOMAIN MODEL
域模型
I will use the following domain model for this answer. Note how there are no JAXB annotations on the model.
我将使用以下域模型来获得此答案。请注意模型上没有JAXB注释。
Customer
顾客
package forum11693552;
import java.util.*;
public class Customer {
private String firstName;
private String lastName;
private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
public void setPhoneNumbers(List<PhoneNumber> phoneNumbers) {
this.phoneNumbers = phoneNumbers;
}
}
PhoneNumber
电话号码
package forum11693552;
public class PhoneNumber {
private String type;
private String number;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
OPTION #1 - Any JAXB (JSR-222) Implementation
选项#1 - 任何JAXB(JSR-222)实现
JAXB is configurartion by exception, this means you only need to add annotations where you want the mapping behaviour to differ from the default. Below is a link to an example demonstrating how to use any JAXB impl without annotations:
JAXB是异常配置,这意味着您只需要在希望映射行为与默认值不同的地方添加注释。下面是一个示例的链接,演示如何在没有注释的情况下使用任何JAXB impl:
Demo
演示
package forum11693552;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Customer customer = new Customer();
customer.setFirstName("Jane");
customer.setLastName("Doe");
PhoneNumber workPhone = new PhoneNumber();
workPhone.setType("work");
workPhone.setNumber("555-1111");
customer.getPhoneNumbers().add(workPhone);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
JAXBElement<Customer> rootElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer);
marshaller.marshal(rootElement, System.out);
}
}
Output
产量
<customer>
<firstName>Jane</firstName>
<lastName>Doe</lastName>
<phoneNumbers>
<number>555-1111</number>
<type>work</type>
</phoneNumbers>
</customer>
For More Information
了解更多信息
- http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics
- http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/TheBasics
OPTION #2 - EclipseLink JAXB (MOXy)'s External Mapping Document
选项#2 - EclipseLink JAXB(MOXy)的外部映射文档
If you do want to customize the mappings, then you may be interested in MOXy's external mapping document extension. A sample mapping document looks like the following:
如果您确实想要自定义映射,那么您可能对MOXy的外部映射文档扩展感兴趣。示例映射文档如下所示:
oxm.xml
oxm.xml
<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="forum11693552">
<java-types>
<java-type name="Customer">
<xml-root-element />
<java-attributes>
<xml-element java-attribute="firstName" name="first-name" />
<xml-element java-attribute="lastName" name="last-name" />
<xml-element java-attribute="phoneNumbers" name="phone-number" />
</java-attributes>
</java-type>
<java-type name="PhoneNumber">
<java-attributes>
<xml-attribute java-attribute="type" />
<xml-value java-attribute="number" />
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
jaxb.properties
jaxb.properties
To enable MOXy as your JAXB provider you need to include a file called jaxb.properties
in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):
要将MOXy作为JAXB提供程序启用,您需要在与域模型相同的程序包中包含一个名为jaxb.properties的文件,并带有以下条目(请参阅:http://blog.bdoughan.com/2011/05/specifying-eclipselink- MOXY-AS-your.html):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
演示
When using EclipseLink MOXy as your JAXB provider (see), you can leverage the external mapping document when you bootstrap your JAXBContext
使用EclipseLink MOXy作为JAXB提供程序(请参阅参考资料)时,可以在引导JAXBContext时利用外部映射文档
package forum11693552;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String,Object>(1);
properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "forum11693552/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, properties);
Customer customer = new Customer();
customer.setFirstName("Jane");
customer.setLastName("Doe");
PhoneNumber workPhone = new PhoneNumber();
workPhone.setType("work");
workPhone.setNumber("555-1111");
customer.getPhoneNumbers().add(workPhone);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
JAXBElement<Customer> rootElement = new JAXBElement<Customer>(new QName("customer"), Customer.class, customer);
marshaller.marshal(rootElement, System.out);
}
}
Output
产量
<?xml version="1.0" encoding="UTF-8"?>
<customer>
<first-name>Jane</first-name>
<last-name>Doe</last-name>
<phone-number type="work">555-1111</phone-number>
</customer>
For More Information
了解更多信息
- http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
- http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html
- http://blog.bdoughan.com/2012/04/extending-jaxb-representing-metadata-as.html
- http://blog.bdoughan.com/2012/04/extending-jaxb-representing-metadata-as.html
#2
5
Have you looked at XStream ? It will deserialise/deserialise a standard POJO without annotations or XSDs. You can provide customisations to affect how elements appear in the XML and pretty much works out-of-the-box.
你看过XStream吗?它将对没有注释或XSD的标准POJO进行反序列化/反序列化。您可以提供自定义以影响元素在XML中的显示方式,并且几乎可以开箱即用。
#3
1
You could write a custom XmlAdapter
and annotate fields of the constrained type with a XmlJavaTypeAdapter
annotation. The basics would be something like this:
您可以使用XmlJavaTypeAdapter批注编写自定义XmlAdapter并注释约束类型的字段。基础知识将是这样的:
public enum CannotBeAnnotated { value1, value2; }
@XmlRootElement(name="client")
public class ClientClass {
@XmlJavaTypeAdapter(Bridge.class)
public CannotBeAnnotated;
}
@XmlRootElement(name="representation")
public class XmlType {
@XmlValue
public String value;
}
public class Bridge extends XmlAdapter<XmlType, CannotBeAnnotated>{
public XmlType marshal(CannotBeAnnotated c) {
XmlType x=new XmlType();
x.value=c.name();
return x;
}
public CannotBeAnnotated unmarshall(XmlType x) {
return CannotBeAnnotated.valueOf(x.value);
}
}
Of course for enums this would not be useful as JAXB knows how to deal with them. I just picked an enum for simplicity so you can see the idea:
当然,对于枚举,这不会有用,因为JAXB知道如何处理它们。我刚刚选择了一个简单的枚举,所以你可以看到这个想法:
- Design an XML representation that you do control
- 设计您可以控制的XML表示
- Write an adapter converting that Java type into the desired type
- 编写将该Java类型转换为所需类型的适配器
- Annotate "client" code referencing the adapter for the desired type
- 注释引用所需类型的适配器的“客户端”代码
- Profit.
- 利润。