2013-03-05 43 views
5

具體MessageBodyWriter說我有在一個JAX-RS 1個環境(RestEasy的2與傑克遜提供商)中的數據類是這樣的:用於現場

class Foo { 
    int id; 
    String name; 
    Bar bar; 

    ... 
} 

Bar感:

class Bar { 
    int one; 
    String two; 
} 

現在我想要Bar以特殊方式序列化(可能取決於所請求的媒體類型(或根據月相),我會編寫一個MessageBodyWriter<Bar>

@Provider 
@Produces("application/json") 
public class BarWriter implements MessageBodyWriter<Bar> { 
    ... 
} 

如果請求對自己喜歡的

@GET @Path("bar") 
public Bar getBar() { return new Bar(...); } 

Bar但是,當我要求Foo

@GET @Path("foo") 
public Foo getFoo() { return new Foo(...); } 

郵件正文作家被忽略,這工作得很好。

現在我想的是,也使用這個MessageBodyWriter,當我返回FooList<Bar>

我認爲後者可以通過只寫一個自定義MessageBodyWriterList情況下可以實現,但對於前一種情況我不能爲包含Bar字段的所有應用程序類編寫郵件正文編寫器。

關於如何解決這個問題的任何想法?我還試圖在Bar實例上使用Jackson序列化程序,但看起來它甚至沒有被RestEasy註冊(然後,我認爲這種方式太脆弱了)。

回答

6

不幸的是,這不是郵件正文編寫者的工作方式。 JAX-RS實現將根據從您的資源方法返回的類型來查找要用於序列化的編寫器。所以你的情況,與Bar定義了自定義的作家,這種資源的方法:

@GET @Path("bar") 
public Bar getBar() { return new Bar(...); } 

的JAX-RS提供者將使用自定義序列化的作家Bar。然而這種資源的方法:

@GET @Path("foo") 
public Foo getFoo() { return new Foo(...); } 

你沒有定製寫入定義,系列化將能夠處理返回類和內容類型的組合,第一個匹配(默認)提供商來處理。關鍵要記住的是,與典型的JSON和XML序列化庫不同,JAX-RS實體提供者是而不是遞歸。也就是說,對於在資源方法中返回的給定對象A,提供程序將嘗試僅爲A定位自定義寫入程序,只有,而不包括A中包含的任何類型作爲變量。

既然你使用的是Jackson,爲什麼不直接爲你的Bar類定義一個自定義序列化程序呢?將處理幾乎你每所描述的情景:

public class BarSerializer extends JsonSerializer<Bar> { 

    @Override 
    public void serialize(final Bar value, final JsonGenerator jgen, 
      final SerializerProvider provider) throws IOException, 
      JsonProcessingException { 

     jgen.writeStartObject(); 
     jgen.writeFieldName("myBar"); 
     jgen.writeString(value.getTwo()); 
     jgen.writeEndObject(); 
    } 
} 

你告訴傑克遜使用此正是如此自定義序列化:

@JsonSerialize(using=BarSerializer.class) 
class Bar { 
    int one; 
    String two; 
} 

最後,不要忘了,如果你預計在同一越來越JSON回如你序列化,你還需要一個自定義JsonDeserializer

爲了得到它的工作,你需要類路徑中的jackson-mapperjackson-jaxrs罐(也可能是jackson-core之一)。

+0

感謝您的解釋。可能痛點顯然是非遞歸性。 我已經在考慮使用JacksonSerializer,但無論出於何種原因,由於我仍在調查的任何原因,RE沒有註冊。 至少我並不完全偏離軌道:) – 2013-03-05 19:08:03

+0

使用RestEasy,確保您實際上已經使用代碼部署了Jackson庫(除了resteasy-jackson提供程序庫)。我假設你用'@JsonSerialize(using = MyCustomSerializer.class)'註釋了你的bean。 – Perception 2013-03-05 19:11:10

+0

感知 - 有趣;會嘗試。你知道是否有需要的最低版本的傑克遜庫?是的,我以這種方式註釋了他們。 – 2013-03-05 20:42:04

1

JAX-RS運行時將只爲資源方法返回的對象查找一個MessageBodyWriter(參見本規範的第4.2.2節「消息正文編寫器」部分),然後該單一MessageBodyWriter完全控制整個對象圖將被返回給客戶端。

爲了實現您想要的行爲,您需要每種媒體類型的自定義MessageBodyWriter,即在圖形中遇到特定類型時,願意將對象圖的一部分的序列化委託給另一個寫入器,然後恢復自己的邏輯。獲取特定類型的代理編寫器不會是一個大問題(注入javax.ws.rs.ext.Providers並呼籲getMessageBodyWriter()),但我不認爲現有的xml/json/etc序列化器是在考慮這種類型的擴展的情況下實現的,所以我猜測你不能只傳達他們。僅僅爲此重新實現一個xml編碼器也不是一個有吸引力的選項。

+0

至少我只尋找一個JSON這個自定義序列:-)感謝您指出該選項WRT代表團。 – 2013-03-05 19:10:34