当jackson反序列化失败时,Jerseyexception映射器无法正常工作

我在我的REST API中使用Jersey 2.10和Jackson序列化/反序列化function。

我的想法是让我的REST API始终返回标准的JSON错误响应。 为此,我有ExceptionMapper类,为Jersey应用程序中抛出的任何exception构建正确的json错误响应。 我还有一个生成相同类型的JSON响应的jsp,我在web.xml中注册为error-page,它涵盖了Jersey加载之前可能出现的所有错误。

但是有一种情况,我的Exception mappers和我的json生成jsp都没有工作,就是当一个坏的形成的json发送到POST REST端点时,它只返回以下消息:

HTTP/1.1 400 Bad Request Server: Apache-Coyote/1.1 Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, DELETE, PUT Content-Type: text/plain Content-Length: 210 Date: Tue, 24 Jun 2014 22:14:11 GMT Connection: close Can not deserialize instance of com.example.rest.User[] out of START_OBJECT token at [Source: org.glassfish.jersey.message.internal.EntityInputStream@1dcccac; line: 1, column: 1] 

如何让Jersey返回我的自定义错误响应而不是这个?

更新:

根据@Lucasz的回答,我做了更多的研究,发现在com.fasterxml.jackson.jaxrs.base包中定义了两个exception映射器( https://github.com/FasterXML/jackson-jaxrs-providers/ tree / master / base / src / main / java / com / fasterxml / jackson / jaxrs / base )JsonMappingExceptionMapper和JsonParseExceptionMapper似乎正在影响我的自定义映射器。

如何取消注册那些映射器?

这就是我目前正在注册映射器的方式:

 @ApplicationPath("/") public class MyApp extends ResourceConfig{ public SyntheticAPIApp() { packages("com.example.resource", "com.example.mapper"); register(org.glassfish.jersey.jackson.JacksonFeature.class); } } 

我用下面的exception映射器测试了它:

 import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; import com.fasterxml.jackson.core.JsonProcessingException; @Provider public class JsonProcessingExceptionMapper implements ExceptionMapper{ public static class Error { public String key; public String message; } @Override public Response toResponse(JsonProcessingException exception) { Error error = new Error(); error.key = "bad-json"; error.message = exception.getMessage(); return Response.status(Status.BAD_REQUEST).entity(error).build(); } } 

它工作。


更新:将JsonParseException更改为JsonProcessingException(更一般)


Update2:为了避免注册不需要的映射器替换

 register(org.glassfish.jersey.jackson.JacksonFeature.class); 

 register(com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.class); 

查看JacksonFeature的源代码,您就会明白发生了什么。

我遇到了同样的问题,之前的回答让我得到了解决方案,但并没有让我当前的泽西(2.22)。 首先,我需要使用https://jersey.java.net/documentation/latest/representations.html中描述的org.glassfish.jersey.spi.ExtendedExceptionMapper

此外,Jersey正在检查exception映射器,该exception映射器尽可能接近抛出的exception(来自org.glassfish.jersey.internal.ExceptionMapperFactory ):

 for (final ExceptionMapperType mapperType : exceptionMapperTypes) { final int d = distance(type, mapperType.exceptionType); if (d >= 0 && d <= minDistance) { final ExceptionMapper candidate = mapperType.mapper.getService(); if (isPreferredCandidate(exceptionInstance, candidate, d == minDistance)) { mapper = candidate; minDistance = d; if (d == 0) { // slight optimization: if the distance is 0, it is already the best case, so we can exit return mapper; } } } } 

因此,我需要准确映射exception而不是更一般的exception。

最后,我的提供者看起来如下:

 @Provider public final class JsonParseExceptionExceptionHandler implements ExtendedExceptionMapper { @Override public Response toResponse(final JsonParseException exception) { exception.printStackTrace(); return Response.status(Response.Status.BAD_REQUEST).entity("JSON nicht in korrektem Format.").build(); } @Override public boolean isMappable(final JsonParseException arg0) { return true; } } 

我使用了“jackson-jaxrs-json-provider 2.8.8”和JAX-RS 2.0

应用程序类 – 您需要注册ExceptionMapper实现类:

 @ApplicationPath("pathApplication") public class ApplicationConfiguration extends Application{ @Override public Set> getClasses() { Set> resources = new HashSet<>(); resources.add(YourJAXRSClass.class); resources.add(JsonJacksonEM.class); //ExceptionMapper class implementation //others resources that you need... return resources; } } 

ExceptionMapper类实现:

 @Provider public class JsonJacksonEM implements ExceptionMapper{ @Override public Response toResponse(JsonParseException exception) { //you can return a Response in the way that you want! return Response.ok(new YourObject()).build(); } } 

我遇到了同样的问题并解决了覆盖ExceptionMapper的问题。 完善! 我需要做的另一件事是不理解100%是如何为我的应用程序覆盖JacksonProvider(我不知道它是否与我使用的Jersey版本相关 – 2.19)。 这是我的web.xml部分覆盖它:

  jersey.config.server.provider.classnames  com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider