web-dev-qa-db-ja.com

@XmlElementを使用してリストに注釈を付ける方法は?

javax.xml.bind.annotation.XmlElementを使用した次の注釈があります。

@XmlElement         
public List<String> getKeywords() {
    return keywords;
}

サンプルコンテンツをマーシャリングすると、次のXMLが生成されます。

<keywords>keyword1</keywords>
<keywords>keyword2</keywords>

次のXMLを取得したいと思います。

<keywords>
    <keyword>keyword1</keyword>
    <keyword>keyword2</keyword>
</keywords>

どのような注釈を使用する必要がありますか?

私はもう試した

@XmlElementWrapper
@XmlElement(name="keyword")

しかし、その後、コンテンツ全体が消えて、結果は次のようになります。

<keywords/>

要素の名前を変更しようとした場合にも同じことが起こります:

@XmlElement(name="keyword")

私は何を間違えていますか?

更新:

最初の回答によるクラスの更新された完全なコードを次に示しますが、まだ機能していません(XMLにマーシャリングされた場合、結果は空のリスト<keywords/>になります)。

import Java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Content {

    private List<String> keywords;

    public Content() {}

    @XmlElementWrapper(name="keywords")
    @XmlElement(name="keyword")
    public List<String> getKeywords() {
        return keywords;
    }

    public void setKeywords(List<String> keywords) {
        this.keywords = keywords;
    }  

}

私も同じ結果で以下を試しました:

import Java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

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

    @XmlElementWrapper(name="keywords")
    @XmlElement(name="keyword")
    private List<String> keywords;

    public Content() {}

    public List<String> getKeywords() {
        return keywords;
    }

    public void setKeywords(List<String> keywords) {
        this.keywords = keywords;
    }  

}

ただし、空のリストではなく<keywords>keyword1</keywords><keywords>keyword2</keywords>が生成されるため、キーワードは空ではありません。

import Java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Content {

    private List<String> keywords;

    public Content() {}

    @XmlElement
    public List<String> getKeywords() {
        return keywords;
    }

    public void setKeywords(List<String> keywords) {
        this.keywords = keywords;
    }  

}

マーシャリングのコードは(JAX-RS)です。

import Java.io.StringWriter;
import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

@Path("process")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_XML)
public class ContentHandler {

    @POST
    public Response process(Content content) {

        StringWriter stringWriter = new StringWriter();
        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(Content.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            jaxbMarshaller.marshal(content, stringWriter);
        } catch (JAXBException e) {
            return Response.serverError().entity(e.getMessage()).build();
        }
        return Response.ok(stringWriter.toString(), MediaType.APPLICATION_XML).build();       
    }

}
27
user3429010

@XmlElementWrapperおよび@XmlElementを活用する必要があります。

Javaモデル

コンテンツ

import Java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Content {

    private List<String> keywords;

    public Content() {}

    @XmlElementWrapper
    @XmlElement(name="keyword")
    public List<String> getKeywords() {
        return keywords;
    }

    public void setKeywords(List<String> keywords) {
        this.keywords = keywords;
    }  

}

デモコード

デモ

import Java.util.*;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Content.class);

        List<String> strings = new ArrayList<String>(2);
        strings.add("foo");
        strings.add("bar");

        Content content = new Content();
        content.setKeywords(strings);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(content, System.out);
    }

}

出力

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<content>
    <keywords>
        <keyword>foo</keyword>
        <keyword>bar</keyword>
    </keywords>
</content>

詳細については

以下は、追加情報を提供する私のブログのいくつかの記事へのリンクです。

45
bdoughan

このフォームを使用します。

@XmlElementWrapper(name="keywords")
@XmlElement(name="keyword")

keywordsの場合、<keywords />を取得することに注意してください。

クラスに(コンテキストに応じて)@XmlRootElement@XmlAccessorType(XmlAccessType.?)アノテーションを追加する必要がある場合があります。私は通常@XmlAccessorType(XmlAccessType.FIELD)を使用し、@XmlElementfieldsに注釈を付けます。

16
Adam Arold

上記の回答-Blaise Doughanは完全に正しい

もう1つの簡単な方法は、-@XmlElementWrapperを記述しなくても

 private List<String> keywords;

 @XmlElementWrapper
    @XmlElement(name="keyword")
    public List<String> getKeywords() {
        return keywords;
    }

この方法で使用できます-クラスレベルでXmlAccessorTypeを記述すると、XML要素名はクラスメンバー名と同じになります-キーワード

import Java.util.List;
import javax.xml.bind.annotation.*;

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

    private List<String> keywords;

    public Content() {}


    public List<String> getKeywords() {
        return keywords;
    }

    public void setKeywords(List<String> keywords) {
        this.keywords = keywords;
    }  

}
0
Ashish Shetkar