2015-04-07 30 views
0

我創建了一個自定義提供程序,它將對象序列化爲JSON,因爲默認的Jackson序列化在使用UTF-8編碼時似乎無法正常工作(它添加了額外的非法字符不被客戶解碼)。Jersey自定義提供程序爲UTF-8編碼拋出IOException

提供者:

@Provider 
@Produces(MediaType.APPLICATION_JSON+"; charset=UTF-8") 
public class JsonSerializer implements MessageBodyWriter<ResponseModel> { 

    @Override 
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    @Override 
    public long getSize(ResponseModel t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return 0; 
    } 

    @Override 
    public void writeTo(ResponseModel entity, Class<?> type, Type genericType, 
      Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, 
      OutputStream entityStream) throws IOException, WebApplicationException {   
     Gson gson = new GsonBuilder().setDateFormat("dd/MM/yyyy HH:mm:ss").create(); 
     JSONObject output = new JSONObject(); 
     output = (JSONObject) JSONValue.parse(gson.toJson(entity)); 
     entityStream.write(output.toString().getBytes()); 
     entityStream.flush(); 
    } 
} 

這裏是我的球衣的servlet的web.xml:

<servlet> 
     <servlet-name>ServletAdaptor</servlet-name> 
     <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 
     <!-- Register resources and providers under com.vogella.jersey.first package. --> 
     <init-param> 
      <param-name>com.sun.jersey.config.property.packages</param-name> 
      <param-value>gr.modus.ext</param-value> 
     </init-param> 
     <!--init-param> 
      <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> 
      <param-value>true</param-value> 
    </init-param--> 
     <init-param> 
      <param-name>jersey.config.server.provider.packages</param-name> 
      <param-value>gr.modus.ext</param-value> 
     </init-param> 
     <load-on-startup>1</load-on-startup> 
    </servlet> 

下面是一個Web服務方法的樣本邏輯:

ResponseModel<AnnouncementStatus> rm = new ResponseModel<AnnouncementStatus>(); 
    rm.setData(AnnouncementUtils.getStatuses(userId)); 
    rm.setSuccess(true); 
    return Response.ok(rm).build(); 

每當我打電話這個方法,它正確地通過我的JsonSerializer,但它給出了以下內部服務器錯誤:

java.nio.charset.MalformedInputException: Input length = 1 at java.nio.charset.CoderResult.throwException(CoderResult.java:260) at java.nio.charset.CharsetDecoder.decode(CharsetDecoder.java:781) at com.sun.faces.application.ByteArrayWebOutputStream.writeTo(ByteArrayWebOutputStream.java:112) at com.sun.faces.application.ViewHandlerResponseWrapper.flushToWriter(ViewHandlerResponseWrapper.java:162)

奇怪的是,當我的註釋產生只是MediaType.APPLICATION_JSON時,一切正常工作。然而,響應數據沒有正確編碼,所以我不得不手動添加編碼,現在我有這個問題...

回答

1

entityStream.write(output.toString().getBytes())是錯誤的。您應該使用getBytes(StandardCharsets.UTF_8)(儘管它似乎到達那裏的一個迂迴的方式,即使這樣,你就不能使用write?)

JSON是總是使用UTF-8序列,所以沒有必要添加"; charset=UTF-8"到內容類型。

+0

我讀到JSON總是使用UTF-8序列化,但由於某種原因,如果我沒有指定它的UTF-8字符集,我的響應頭部會有'ISO-8859'charse。當我使用servlet時,只需設置響應的內容類型即可完美工作:'response.setContent(「text/javascript; charset = utf-8」)'。 另外我沒有得到關於'write'的部分。我應該避免使用entityStream? – Konstantine

+0

將'getBytes()'改爲'getBytes(StandardCharsets.UTF_8)'似乎可以避免異常。 – Konstantine