1

なぜリスト型がシリアル化されないのかについて多くの質問がありましたが、単純な方法でリスト型の Bean を提供するための良い方法は何かを疑問に思っています。

これまでのところ、ラッパーをサポートするための内部クラスを作成してきましたが、すべての pojo に対して行う必要があるため、配管は好きではありません。

顧客クラスは次のようになります。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

    private int id;
    private String name;

    // field accessors

    @XmlRootElement(name = "customers")
    @XmlAccessorType(XmlAccessType.FIELD)
    public static final class CustomerList {
        private List<Customer> customer;
        public CustomerList() {
            this.customer = new ArrayList<>();
        }
        public DataList(List<Customer> list) {
            this.customer = list;
        }
        // customer accessors.
    }

}

ジェネリッククラスXmlList<T>を作成して、戻り時に新しいインスタンスを作成しようとしましたが、JAXBはこれを気に入らないようです。

JSON と XML の両方をサポートする必要がある Spring/MVC RESTful アプリケーションでこれを使用しています。私の JSON は配列として表す必要があります。これにより、このメソッドは、JSON 呼び出し内に実装を配置してから XML 呼び出しでラップすることで、両方を簡単に促進できます。

4

4 に答える 4

1

これが私がこれを行う方法です。

@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();
    }
}

ブレット・ライアンのコメントによる更新

ここには、完全な機能を備えたソース コードが付属しています。

完全な mavenized プロジェクトは、http: //code.google.com/p/jinahya/source/browse/trunk/com.googlecode.jinahya/stackoverflow/ で確認できます。

プロパティではなくフィールドを使用するように制御する場合、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 の 2 回目のコメントによる更新

@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>
于 2012-08-16T14:03:30.000 に答える
0

これは私が考える別の適切な方法かもしれません。

@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response readItems() {

    final List<Item> items = ...;

    return Response.ok(new GenericEntity<List<String>>(list) {}).build();
}
于 2013-03-21T04:03:00.150 に答える
0

さらなる読者のために。

JAX-RS の自動複数形化について話している興味深いブログ エントリを見つけました。 https://blogs.oracle.com/PavelBucek/entry/returning_xml_representation_of_list

この機能が実装固有のものかどうかはわかりません。

誰もが、プラットフォームが何をどのように提供するかを試す必要があります。

@GET
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public List<Item> read() {

    final List<Item> items = ... // is the variable name relevant 

    return items;
}
于 2012-08-20T12:23:26.140 に答える