Jerseyを使用して、サーバーコンポーネントのREST Webサービスを作成しています。
リストでシリアル化するJAXB注釈付きオブジェクトは次のようになります。
_@XmlRootElement(name = "distribution")
@XmlType(name = "tDistribution", propOrder = {
"id", "name"
})
public class XMLDistribution {
private String id;
private String name;
// no-args constructor, getters, setters, etc
}
_
私はRESTリソースを持ち、次のような1つのディストリビューションを取得します。
_@Path("/distribution/{id: [1-9][0-9]*}")
public class RESTDistribution {
@GET
@Produces("application/json")
public XMLDistribution retrieve(@PathParam("id") String id) {
return retrieveDistribution(Long.parseLong(id));
}
// business logic (retrieveDistribution(long))
}
_
また、すべてのディストリビューションのリストを取得するためのRESTリソースがあります。これは次のようになります。
_@Path("/distributions")
public class RESTDistributions {
@GET
@Produces("application/json")
public List<XMLDistribution> retrieveAll() {
return retrieveDistributions();
}
// business logic (retrieveDistributions())
}
_
ContextResolverを使用してJAXBシリアル化をカスタマイズします。現在、次のように構成されています。
_@Provider
@Produces("application/json")
public class JAXBJSONContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
public JAXBJSONContextResolver() throws Exception {
JSONConfiguration.MappedBuilder b = JSONConfiguration.mapped();
b.nonStrings("id");
b.rootUnwrapping(true);
b.arrays("distribution");
context = new JSONJAXBContext(b.build(), XMLDistribution.class);
}
@Override
public JAXBContext getContext(Class<?> objectType) {
return context;
}
}
_
両方のRESTリソースはコンテキストリゾルバと同様に機能します。これは最初の出力の例です:
_// path: /distribution/1
{"id":1,"name":"Example Distribution"}
_
それはまさに私が欲しいものです。これはリストの出力例です:
_// path: /distributions
{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}
_
これは私が望むものではありません。
なぜdistribution
タグで囲まれているのかわかりません。コンテキストリゾルバで.rootUnwrapping(true)
で削除したかったのですが、明らかにそれは別の囲んでいるタグを削除するだけです。これは.rootUnwrapping(false)
の出力です:
_// path: /distribution/1
{"distribution":{"id":1,"name":"Example Distribution"}} // not ok
// path: /distributions
{"xMLDistributions":{"distribution":[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]}}
_
また、要素が1つだけであっても、常にJSON配列を取得するように.arrays("distribution")
を構成する必要がありました。
理想的には、出力としてこれが欲しいです:
_// path: /distribution/1
{"id":1,"name":"Example Distribution"} // currently works
// path: /distributions
[{"id":1,"name":"Sample Distribution 1"},{"id":2,"name":"Sample Distribution 2"}]
_
_List<XMLDistribution>
_、XMLDistributionList
(リストを囲むラッパー)、_XMLDistribution[]
_を返そうとしましたが、ディストリビューションの単純なJSON配列を取得する方法が見つかりませんでした必要な形式。
JSONConfiguration.natural()
、JSONConfiguration.mappedJettison()
などによって返される他の表記法も試してみましたが、必要なものに似たものを得ることができませんでした。
これを行うためにJAXBを設定することが可能であるかどうかを知っていますか?
私は解決策を見つけました。JAXBJSONシリアライザーを、Jacksonのような動作の良いJSONシリアライザーに置き換えてください。簡単な方法はjackson-jaxrsを使用することです。これは既にあなたのためにそれを行っています。クラスはJacksonJsonProviderです。必要なのは、Jersey(または別のJAX-RS実装)がスキャンするようにプロジェクトのweb.xmlを編集することだけです。追加する必要があるものは次のとおりです。
<init-param>
<param-name>com.Sun.jersey.config.property.packages</param-name>
<param-value>your.project.packages;org.codehaus.jackson.jaxrs</param-value>
</init-param>
そして、それだけです。 JacksonはJSONのシリアル化に使用され、リストと配列に期待される方法で動作します。
より長い方法は、「application/json」を生成するために登録された独自のカスタムMessageBodyWriterを記述することです。以下に例を示します。
@ Provider @ Produces( "application/json") publicクラスJsonMessageBodyWriterはMessageBodyWriterを実装します{ @Override public long getSize(Object obj 、クラスタイプ、Type genericType、 Annotation []アノテーション、MediaType mediaType){ return -1; } @Override public boolean isWriteable(Class type、Type genericType、 Annotation annotations []、MediaType mediaType){ return true; } @Override public void writeTo(Object target、Class type、Type genericType、 Annotation [] annotations、MediaType mediaType、 MultivaluedMap httpHeaders、OutputStream outputStream) throws IOException { new ObjectMapper()。writeValue(outputStream、target); } }
上記の既製のソリューションのように、web.xmlにパッケージが含まれていることを確認する必要があります。
いずれにせよ:出来上がり!適切に形成されたJSONが表示されます。
ここからジャクソンをダウンロードできます: http://jackson.codehaus.org/
ジョンハタンの答えはすばらしく、私にとって非常に役に立ちました。
ただのアップグレード:
jacksonのバージョン2.x(バージョン2.1など)を使用する場合、クラスはcom.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProviderであるため、web.xmlは次のようになります。
<init-param>
<param-name>com.Sun.jersey.config.property.packages</param-name>
<param-value>your.project.packages;com.fasterxml.jackson.jaxrs.json</param-value>
</init-param>