泽西/杰克逊 异常问题与异常映射器

我正在使用泽西岛向外界提供java REST服务。我提供了一些采用JSON的函数,我将Jackson框架与球衣结合使用,将它们转换为POJO。

我有一个问题,如果将错误的jackson格式发送到服务器,则答案(http响应的内容)是jackson特定的异常描述。如果我有一个带有属性“surname”的POJO,并将json字符串中的“sursname”发送到服务器,我得到:

Unrecognized field "sursname" (Class XY), not marked as ignorable at [Source: sun.net.httpserver.FixedLengthInputStream@903025; line: 1, column: 49] (through reference chain: XY["sursname"])

这很好,但我想有自己的响应内容,例如我自己的错误代码。我已经编写了一个自定义异常映射器,它应该映射所有可抛出的。

@Provider
public class WebserviceExceptionMapper implements ExceptionMapper<Throwable> {

@Override
public Response toResponse(Exception e) {
    e.printStackTrace();
    return Response.status(400).entity("{\"errorcode\":\"CRITICAL_ERROR\"}").type(MediaType.APPLICATION_JSON).build();
    }
}

似乎在我的Webservice方法被调用之前抛出了jackson异常,所以我没有机会映射它?

有人有想法吗?非常感谢我的英语;)


答案 1

您的自定义 ExceptionMapper 不捕获异常的原因是 Jackson 库提供了自己的异常映射器,该映射器会在异常被基因异常映射器捕获之前捕获异常。

有些人建议你应该为JsonParseExceptionMapper和JacksonMappingExceptionMapper实现自己的异常映射器,但是,这会产生不一致的结果。在他们的GitHub上查看这个问题

若要解决此问题,必须确保未注册任何内置异常映射器。如果您使用 json 的 jackson-jaxrs-providers 库:jackson-jaxrs-json-provider,请确保仅在 Application 类中注册 JacksonJaxbJsonProvider.classJacksonJsonProvider.class

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(JacksonJaxbJsonProvider.class)
    }
}

请注意 JacksonFeature.class,因为它注册了内置的 ExceptionMappers。还要远离 jersey-media-json-jackson 库,该库会自动添加一些内置的异常映射器,而无需执行任何操作。


答案 2

不久前,我在使用Jackson和Apache CXF时遇到了类似的问题。如果异常未在我的 JAX-RS 方法中发生,而是在 .在我的情况下,解决方案是扩展,捕获特定的Jackson json异常,并将其作为WebApplicationException重新抛出。JacksonJsonProviderJacksonJsonProvider

这是我的扩展的重写的readFrom方法:JacksonJsonProvider

    @Override
    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
            MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
        try {
            return super.readFrom(type, genericType, annotations, mediaType, httpHeaders, entityStream);
        } catch (JsonParseException jpe) {
            throw new WebApplicationException(jpe, Response.status(Status.BAD_REQUEST)
                    .entity(new ErrorEntity("Malformed json passed to server: \n" + jpe.getMessage())).build());
        } catch (JsonMappingException jme) {
            throw new WebApplicationException(jme, Response
                    .status(Status.BAD_REQUEST)
                    .entity(new ErrorEntity("Malformed json passed to server, incorrect data type used: \n"
                            + jme.getMessage())).build());
        }
    }

推荐