这是我如何做到这一点的。
@XmlRootElement // or @XmlTransient if you want to
public class Plural<S> {
public static <P extends Plural<S>, S> P newInstance(
final Class<P> pluralType, final Collection<S> elms) {
P lt = (P) pluralType.newInstance();
lt.singulars = new ArrayList<>(elms);
return lt;
}
protected Collection<S> getSingulars() {
if (singulars == null) {
singulars = new ArrayList<S>();
}
return singulars;
}
private Collection<S> singulars;
}
然后,您可以制作任何单数类型的任何所需复数类型。也许你不喜欢你应该为所有单数类型创建所有复数类,但它可能真的很有帮助,尤其是当你想让那些客户端开发人员看起来更漂亮时。
@XmlRootElement
public class Customers extends Plural<Customer> {
@XmlElement(name = "customer")
public Collection<Customer> getCustomers() {
return getSingulars();
}
}
@XmlRootElement
public class Items extends Plural<Item> {
@XmlElement(name = "item")
public Collection<Item> getItems() {
return getSingulars();
}
}
@XmlRootElement
public class Invoices extends Plural<Invoice> {
@XmlElement(name = "invoice")
public Collection<Invoice> getInvoices() {
return getSingulars();
}
}
@XmlRootElement
public class BrettRyans extends Plural<BrettRyan> {
@XmlElement(name = "brettRyan")
public Collection<BrettRyan> getBrettRyans() {
return getSingulars();
}
}
根据布雷特瑞恩的评论更新
这里有功能齐全的源代码。
您可以在http://code.google.com/p/jinahya/source/browse/trunk/com.googlecode.jinahya/stackoverflow/查看完整的 mavenized 项目
如果您控制使用字段而不是属性,则 JAXB 不需要设置器。
@XmlTransient
public class Plural<S> {
public static <P extends Plural<S>, S> P newInstance(
final Class<P> pluralType) {
return newInstance(pluralType, Collections.<S>emptyList());
}
public static <P extends Plural<S>, S> P newInstance(
final Class<P> pluralType, final Collection<? extends S> singulars) {
try {
final P plural = pluralType.newInstance();
plural.getSingulars().addAll(singulars);
return plural;
} catch (InstantiationException ie) {
throw new RuntimeException(ie);
} catch (IllegalAccessException iae) {
throw new RuntimeException(iae);
}
}
protected Collection<S> getSingulars() {
if (singulars == null) {
singulars = new ArrayList<S>();
}
return singulars;
}
private Collection<S> singulars;
}
@XmlAccessorType(XmlAccessType.NONE)
public class Item {
public static Item newInstance(final long id, final String name) {
final Item instance = new Item();
instance.id = id;
instance.name = name;
return instance;
}
@Override
public String toString() {
return id + "/" + name;
}
@XmlAttribute
private long id;
@XmlValue
private String name;
}
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement
public class Items extends Plural<Item> {
@XmlElement(name = "item")
public Collection<Item> getItems() {
return getSingulars();
}
}
测试...
public class ItemsTest {
@Test
public void testXml() throws JAXBException, IOException {
final Items marshallable = Plural.newInstance(Items.class);
for (int i = 0; i < 5; i++) {
marshallable.getItems().add(Item.newInstance(i, "name" + i));
}
for (Item item : marshallable.getItems()) {
System.out.println("marshallable.item: " + item);
}
final JAXBContext context = JAXBContext.newInstance(Items.class);
final Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
marshaller.marshal(marshallable, baos);
baos.flush();
final Unmarshaller unmarshaller = context.createUnmarshaller();
final Items unmarshalled = (Items) unmarshaller.unmarshal(
new ByteArrayInputStream(baos.toByteArray()));
for (Item item : unmarshalled.getItems()) {
System.out.println("unmarshalled.item: " + item);
}
}
}
印刷
marshallable.item: 1/name1
marshallable.item: 2/name2
marshallable.item: 3/name3
marshallable.item: 4/name4
unmarshalled.item: 0/name0
unmarshalled.item: 1/name1
unmarshalled.item: 2/name2
unmarshalled.item: 3/name3
unmarshalled.item: 4/name4
根据 Brett Ryan 的第二条评论更新
@Test
public void testXsd() throws JAXBException, IOException {
final JAXBContext context = JAXBContext.newInstance(Items.class);
context.generateSchema(new SchemaOutputResolver() {
@Override
public Result createOutput(final String namespaceUri,
final String suggestedFileName)
throws IOException {
return new StreamResult(System.out) {
@Override
public String getSystemId() {
return "noid";
}
};
}
});
}
当Plural
用@XmlRootElement
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="items" type="items"/>
<xs:element name="plural" type="plural"/>
<xs:complexType name="items">
<xs:complexContent>
<xs:extension base="plural">
<xs:sequence>
<xs:element name="item" type="item" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="plural">
<xs:sequence/>
</xs:complexType>
<xs:complexType name="item">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:long" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
当Plural
用@XmlTransient
.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="items" type="items"/>
<xs:complexType name="items">
<xs:sequence>
<xs:element name="item" type="item" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="item">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="id" type="xs:long" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>