Jersey 自定义提供程序为 UTF-8 编码抛出 IOException
Jersey custom provider throws IOException for UTF-8 encoding
我创建了一个将我的对象序列化为 JSON 的自定义提供程序,因为默认的 Jackson 序列化在使用 UTF-8 编码时似乎无法正常工作(它添加了无法被解码的额外非法字符客户)。
提供商:
@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
时,一切正常。但是响应数据没有正确编码所以我被迫手动添加编码,现在我遇到了这个问题...
entityStream.write(output.toString().getBytes())
是错误的。你应该使用 getBytes(StandardCharsets.UTF_8)
(虽然这似乎是一种迂回的方式,即使那样。你不能使用 write
吗?)
JSON 总是 以 UTF-8 序列化,因此不需要在内容类型中添加 "; charset=UTF-8"
。
我创建了一个将我的对象序列化为 JSON 的自定义提供程序,因为默认的 Jackson 序列化在使用 UTF-8 编码时似乎无法正常工作(它添加了无法被解码的额外非法字符客户)。
提供商:
@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
时,一切正常。但是响应数据没有正确编码所以我被迫手动添加编码,现在我遇到了这个问题...
entityStream.write(output.toString().getBytes())
是错误的。你应该使用 getBytes(StandardCharsets.UTF_8)
(虽然这似乎是一种迂回的方式,即使那样。你不能使用 write
吗?)
JSON 总是 以 UTF-8 序列化,因此不需要在内容类型中添加 "; charset=UTF-8"
。