私は、Jerseyの文字列のリストをJSONおよびXMLとして返そうとしています。これは些細なことだと思いました。
私の最初の試みはこのようなものを書くことでした
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/bar")
public List<String> get() {
return dao.get();
}
そして、私はこれに似た出力を期待していました:["string1"、...、 "stringN]残念ながら私はこれを得ました:
com.Sun.jersey.api.MessageException: A message body writer for Java class Java.util.LinkedList, and Java type Java.util.List<Java.lang.String>, and MIME media type application/json was not found
次に、ListのラッパーStringListを作成しました
@XmlRootElement
public class StringList {
private List<String> data;
public StringList() {
}
public StringList(List<String> data) {
this.data = data;
}
public List<String> getData() {
return data;
}
public void setData(List<String> data) {
this.data = data;
}
}
ファサードを
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/foo")
public StringList stringlist() {
return new StringList(sl());
}
これは、1を超えるアイテムを持つリストに最適です。
{"data":["foo","bar"]}
残念ながら、1つまたは0つの要素に対して2つの予期しない結果が得られます
{"data": "just one"} // for one element i would expect {"data": ["just one"]}
null // for no elements i would expect {"data": []}
私は完全に間違っていることをしていますか?どうすれば修正できますか?
javax.ws.rs.core.GenericEntity
:
@GET
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
@Path("/foo")
public GenericEntity<List<String>> stringlist()
{
List<String> list = Arrays.asList("test", "as");
return new GenericEntity<List<String>>(list) {};
}
さて、サンプルを検索して修正できます
これは機能しますが、JSONにのみ使用でき、XMLには使用できません
@GET
@Produces({MediaType.APPLICATION_JSON})
@Path("/get")
public JSONArray get() {;
return new JSONArray(dao.getStringList());
}
問題を修正しますが、一般的なアプローチもありますか?
Jerseyに希望どおりにリストを出力するように説得するには、独自のContextResolverを提供する必要があります。
@Provider
public class JaxbContentResolver implements ContextResolver<JAXBContext> {
private Log log = LogFactory.getLog(getClass());
private JAXBContext context;
public JaxbContentResolver() throws JAXBException {
Class[] types = {StringList.class};
context = new JSONJAXBContext(JSONConfiguration.mapped().rootUnwrapping(true).arrays("data").build(), types);
}
@Override
public JAXBContext getContext(Class<?> objectType) {
log.trace("Entering Test-getContext for type: " + objectType.getSimpleName());
return context;
}
}
この方法のリストは、希望どおりに表示されます。
注:このアプローチの欠点の1つは、コードで1つの追加の場所を維持する必要があることです。別の(リストラッパー)クラスをRESTインターフェイスに追加する場合は、上記のコードに移動して、そのクラスをContextResolverに追加することを忘れないでください...
提供された回答に加えて、MessageBodyWriter not found
、次のような依存関係を追加してみてください:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
これに対する私の解決策はラッパークラスでした(どこかで見つけました)。現在は機能しています。ルート要素としてjavas Listクラスをサポートしないことの背後にある考えを理解していません。多分それは私が知らないjson仕様/ベストプラクティスに関係しています。
しかし今のところこれを使用しています:
public class Houses {
private List<String> houses;
// Needed for jersey
public Houses() { }
public Houses(List<String> houses) {
this.houses = houses;
}
public void setHouses(List<String> houses) {
this.houses = houses;
}
public List<String> getHouses() {
return this.houses;
}
}
代替のJSON設定JSONConfiguration.natural()
を使用する必要があります。
その代替構成をプロバイダーとして使用して独自のContextResolver
を作成し、それが担当するクラスを通知するのが最善です。
代替構成をグローバルに別の方法で使用する方法を知りません。