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"