[英]How to reuse Jersey's JSON/JAXB for serialization?
我有一個使用Jersey實現的JAX-RS REST服務。 JAX-RS / Jersey的一個很酷的功能就是如何輕松地將POJO變成REST服務,只需簡單地添加一些Java注釋......包括使用JAXB注釋將POJO轉換為JSON的簡單機制。
現在,我希望能夠利用這種非常酷的JSON-ifying功能用於非REST目的 - 我希望能夠將這些對象中的一些序列化為磁盤,作為JSON文本。 這是我想要序列化的示例JAXB對象:
@XmlRootElement(name = "user")
public class UserInfoImpl implements UserInfo {
public UserInfoImpl() {}
public UserInfoImpl(String user, String details) {
this.user = user;
this.details = details;
}
public String getUser() { return user; }
public void setUser(String user) { this.user = user; }
public String getDetails() { return details; }
public void setDetails(String details) { this.details = details; }
private String user;
private String details;
}
澤西可以將其中一個變成json而沒有額外的信息。 我想知道澤西是否已經在API中公開了這個功能,以滿足我的需求? 到目前為止我找不到運氣了......
謝謝!
更新2009-07-09 :我已經了解到我可以使用Providers對象幾乎完全按照我的意願行事:
@Context Providers ps;
MessageBodyWriter uw = ps.getMessageBodyWriter(UserInfoImpl.class, UserInfoImpl.class, new Annotation[0], MediaType.APPLICATION_JSON_TYPE);
uw.writeTo(....)
...這將對象作為json寫入任何輸出流,這對我來說是完美的,但我只能使用@Component對象中的@Context來獲取Providers對象。 有沒有人知道如何從常規的,未注釋的POJO訪問它? 謝謝!
Jersey使用幾個不同的框架,具體取決於您使用的是mapped(),badgerfish()還是natural()表示法。 自然通常是人們想要的。 我相信這是使用非常好的(並且非常快)獨立的Jackson JSON處理器實現的,它來自Object-> JAXB-> JSON。 但Jackson也提供了自己的JAX-RS提供程序來直接使用Object-> JSON。
實際上,他們甚至添加了對JAXB注釋的支持。 看一下
http://wiki.fasterxml.com/JacksonJAXBAnnotations
我認為這最終是你在尋找的。 傑克遜做對象< - > JSON處理......澤西只是為你打電話
這是一個使用JAXB將對象映射到JSON的簡單示例(使用Jackson):
http://ondra.zizka.cz/stranky/programovani/java/jaxb-json-jackson-howto.texy
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(pojoObject);
在序列化為XML時,JAXB注釋工作正常。 主要問題是JAXB不支持空數組。 所以當序列化這樣的東西時......
List myArray = new ArrayList();
...通過jaxb anottations到json所有空數組都變為null而不是[]。
要解決這個問題,您可以通過jackson直接將您的pojos序列化為json。
從Jersey的用戶指南中查看: http : //jersey.java.net/nonav/documentation/latest/user-guide.html#d0e1959
這是在沒有JAXB的情況下使用Jackson提供程序的最佳方式。 此外,您可以隨時使用最新版本的jackson,通過網絡下載jackson-all-xyz-jar。
這個方法不會干擾你的jaxb注釋,所以我建議試一試!
通過一點Jersey專用引導,您可以使用它為您創建必要的JSON對象。 您需要包含以下依賴項(您可以使用bundle,但如果您使用Weld進行測試,則會導致問題):
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.12</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.12</version>
</dependency>
從那里你可以創建一個JAXB注釋類。 以下是一個例子:
@XmlRootElement
public class TextMessage {
private String text;
public String getText() { return text; }
public void setText(String s) { this.text = text; }
}
然后,您可以創建以下單元測試:
TextMessage textMessage = new TextMessage();
textMessage.setText("hello");
textMessage.setUuid(UUID.randomUUID());
// Jersey specific start
final Providers ps = new Client().getProviders();
// Jersey specific end
final MultivaluedMap<String, Object> responseHeaders = new MultivaluedMap<String, Object>() {
@Override
public void add(final String key, final Object value) {
}
@Override
public void clear() {
}
@Override
public boolean containsKey(final Object key) {
return false;
}
@Override
public boolean containsValue(final Object value) {
return false;
}
@Override
public Set<java.util.Map.Entry<String, List<Object>>> entrySet() {
return null;
}
@Override
public List<Object> get(final Object key) {
return null;
}
@Override
public Object getFirst(final String key) {
return null;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Set<String> keySet() {
return null;
}
@Override
public List<Object> put(final String key, final List<Object> value) {
return null;
}
@Override
public void putAll(
final Map<? extends String, ? extends List<Object>> m) {
}
@Override
public void putSingle(final String key, final Object value) {
}
@Override
public List<Object> remove(final Object key) {
return null;
}
@Override
public int size() {
return 0;
}
@Override
public Collection<List<Object>> values() {
return null;
}
};
final MessageBodyWriter<TextMessage> messageBodyWriter = ps
.getMessageBodyWriter(TextMessage.class, TextMessage.class,
new Annotation[0], MediaType.APPLICATION_JSON_TYPE);
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
Assert.assertNotNull(messageBodyWriter);
messageBodyWriter.writeTo(textMessage, TextMessage.class,
TextMessage.class, new Annotation[0],
MediaType.APPLICATION_JSON_TYPE, responseHeaders, baos);
final String jsonString = new String(baos.toByteArray());
Assert.assertTrue(jsonString.contains("\"text\":\"hello\""));
這種方法的優點是它可以保留JEE6 API中的所有內容,除了測試和獲取提供程序之外,不需要明確需要任何外部庫。 但是,您需要創建MultivaluedMap的實現,因為標准中沒有提供任何內容,我們實際上並未使用它。 它也可能比GSON慢,很多復雜得多必要的。
由於Jersey是JAX-RS的參考實現,而JAX-RS完全專注於提供實現REST服務端點的標准方法,因此將有效負載序列化的問題留給其他標准。
我認為,如果它們在JAX-RS標准中包含對象序列化,它很快就會成為一個很難實現的大型多頭野獸,並且會忽略它的一些重點。
我很欣賞Jersey在提供簡潔易用的REST端點方面的重點。 在我的情況下,我只是將一個包含所有JAXB管道的父類子類化,因此二進制和XML之間的編組對象非常干凈。
我理解XML視圖,但它會表現出一些先見之明,需要JSON支持POJO作為標准設備。 如果您的實現是JSON並且您的客戶端是JavaScript RIA,則必須使用特殊字符來管理JSON標識符是沒有意義的。
而且,Java Bean並不是POJO。 我想在我的Web層的外表面上使用類似的東西:
public class Model
{
@Property height;
@Property weight;
@Property age;
}
沒有默認構造函數,沒有getter / setter噪聲,只有一個帶有我自己的注釋的POJO。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.