Java クラスを XML にマーシャリングおよびアンマーシャリングする必要があります。クラスは私が所有していないため、JAXB を使用できるように注釈を追加することはできません。
指定された制約で Java を XML に変換する良い方法はありますか?
また、ツールが役立つかもしれないと考えましたが、同じことを行う Java API があればもっと興味があります。
Java クラスを XML にマーシャリングおよびアンマーシャリングする必要があります。クラスは私が所有していないため、JAXB を使用できるように注釈を追加することはできません。
指定された制約で Java を XML に変換する良い方法はありますか?
また、ツールが役立つかもしれないと考えましたが、同じことを行う Java API があればもっと興味があります。
注: 私はEclipseLink JAXB (MOXy)のリーダーであり、JAXB (JSR-222)エキスパート グループのメンバーです。
ドメインモデル
この回答には、次のドメイン モデルを使用します。モデルに JAXB アノテーションがないことに注意してください。
お客様
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;
}
}
電話番号
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;
}
}
オプション #1 - 任意の JAXB (JSR-222) 実装
JAXB は例外的に構成されます。つまり、マッピングの動作をデフォルトとは異なるものにする必要がある場合にのみ、注釈を追加する必要があります。以下は、注釈なしで任意の JAXB impl を使用する方法を示す例へのリンクです。
デモ
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);
}
}
出力
<customer>
<firstName>Jane</firstName>
<lastName>Doe</lastName>
<phoneNumbers>
<number>555-1111</number>
<type>work</type>
</phoneNumbers>
</customer>
詳細については
オプション #2 - EclipseLink JAXB (MOXy) の外部マッピング ドキュメント
マッピングをカスタマイズしたい場合は、MOXy の外部マッピング ドキュメント拡張に関心があるかもしれません。サンプル マッピング ドキュメントは次のようになります。
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
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
デモ
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);
}
}
出力
<?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>
詳細については
XStreamを見たことがありますか?アノテーションやXSDなしで標準のPOJOを逆シリアル化/逆シリアル化します。XMLでの要素の表示方法に影響を与えるカスタマイズを提供でき、ほとんどそのままで機能します。
注釈を使用して、制約された型のカスタムXmlAdapter
フィールドと注釈を付けることができますXmlJavaTypeAdapter
。基本は次のようなものになります。
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);
}
}
もちろん、列挙型の場合、JAXB はそれらの処理方法を知っているため、これは役に立ちません。簡単にするために列挙型を選んだだけなので、アイデアがわかります。