Как отобразить связанные с JSON ошибки анализа в ответ JSON в Джерси
Я определил тип данных и его API:
public class DataType {
@Column
private String name;
}
// API is:
public class DataTypeAPI {
@POST
@Path("/")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@ManagedAsync
public void createDataType(
final DataType dataType,
) {
...
asyncResponse.resume(Response.status(Response.Status.CREATED)
.entity(dataType)
.build());
}
}
Все хорошо, если я поставил {
"name": "xxx"
}
,
но когда я отправил { "name1": "xxx" }
Я получил следующее text/plain
ответ:
Unrecognized field "name1" (class com.xxx.datatypes.DataType), not marked as ignorable (1 known properties: "name"])
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@526e34b1; line: 2, column: 15] (through reference chain: com.xxx.datatypes.DataType["name1"])
Я предпочитаю конвертировать вышеуказанную ошибку в ответ JSON. но событие, которое я добавил следующее сопоставление исключений, не возвращает ответ JSON.
@Provider
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
public Response toResponse(Throwable ex) {
System.out.println("GenericExceptionMapper");
ex.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorBody(500, ex.getMessage()))
.type(MediaType.APPLICATION_JSON)
.build();
}
}
Почему мой вышеупомянутый картограф исключений не может поймать ошибку анализа джерси. Может ли кто-нибудь объяснить мне это? Спасибо
ОБНОВИТЬ
У меня есть два вопроса:
1, как сделать ответ, чтобы быть application/json
вместо text/plain
?
2, почему мой картограф исключений не перехватил возникшее исключение и не сопоставил его с ответом json?
ОБНОВИТЬ
Я добавил следующий маппер:
public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> {
public Response toResponse(JsonMappingException ex) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(new ErrorBody(500, ex.getMessage()))
.type(MediaType.APPLICATION_JSON)
.build();
}
}
Теперь я могу получить ответ JSON: {
"code": 500,
"message": "Unrecognized field \"name1\" (class com.xxx.datatypes.DataType), not marked as ignorable (1 known properties: \"name\"])\n at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@1d8cd12a; line: 2, column: 15] (through reference chain: class com.xxx.datatypes.DataType[\"name1\"])"
}
У меня еще есть два вопроса:
1, почему мой универсальный сопоставитель исключений не может его поймать.
2, преобразователь исключений отображения json не может отобразить следующее исключение Unexpected character ('}' (code 125)): was expecting double-quote to start field name
at [Source: org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream@7615743c; line: 3, column: 2]
когда {"name": "xxxx",}
опубликовано (запятая, добавлено для тестирования)
4 ответа
Я встретил ту же проблему, и я решил ее. Я пытаюсь объяснить ваш вопрос:
И то, и другое. И Джерси определил для и для .
- Если вы определяете свой собственный преобразователь для
JsonProcessingException
(или более широкий преобразователь исключений), он не может поймать и , потому что у этих двух исключений есть свой преобразователь. Если их нет, ваш картограф может поймать. - Если вы определяете свой собственный картограф (например,
XxxJsonMappingExceptionMapper
заJsonMappingException
а такжеYyyJsonParseExceptionMapper
заJsonParseException
), вы можете обнаружить, что иногда вы можете перехватывать эти исключения, иногда нет, это зависит от того, работает ли ваш собственный маппер или работает маппер джерси. Теперь вы можете добавить (javax.annotation.Priority) в свой преобразователь, чтобы убедиться, что он работает. см. Джексон JsonParseExceptionMapper и JsonMappingExceptionMapper затеняет пользовательский сопоставитель .
вернуться к вашему вопросу:
- Ваш общий преобразователь исключений не может его перехватить, потому что у этих исключений есть собственный преобразователь исключений (
JsonMappingExceptionMapper
и , они имеют более высокий приоритет). - Вы не можете поймать исключение, потому что ваш собственный картограф затенен
JsonParseExceptionMapper
. Попробуйте выяснить, добавив@Priority(1)
на свой собственный маппер
почему мой универсальный картограф исключений не может поймать это.
Потому что модуль Jackson-JAXRS уже поставляется с ExceptionMappers для исключений Джексона.
Преобразователь исключений сопоставления json не может сопоставить следующее исключение
Я не проверял это, но, скорее всего, потому что это не исключение отображения, а исключение синтаксического анализа. Джексон имеет оба JsonParseException
а также JsonMappingException
, В предыдущей ссылке вы можете видеть, что Джексон поставляется с ExceptionMapper для обоих JsonMappingException
а также JsonParseException
, Вы переопределяете маппер только для JsonMappingException
,
Нераспознанное поле "name1" (класс com.xxx.datatypes.DataType), не помеченное как игнорируемое (1 известных свойств: "name"])
Если вы посмотрите на возникшее исключение, то совершенно очевидно, что ваш класс POJO имеет свойство с именем name
не name1
,
И вы пытаетесь опубликовать свой JSON с именем свойства name1
,
{ "name1": "xxx" }
И это не было признано name1
не был определен вместо name
,
public class DataType {
@Column
private String name;
}
И это причина, она отлично работает в другом случае, когда вы публикуете JSON как
{ "name": "xxx" }
Я использую org.glassfish.jersey-jackson-2.33. когда вы регистрируете JacksonFeature, который отвечает за ответ Джексона по умолчанию с помощью «withoutExceptionMappers())». тогда, если у вас есть какой-либо сопоставитель исключений Throwable, он будет улавливать вместо сопоставителя Джексона по умолчанию. вы также можете написать свой преобразователь JsonParseException, если вы не используете преобразователь Throwable.
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
public class JerseyApplication extends ResourceConfig {
//register(JacksonFeature.class);
register(JacksonFeature.withoutExceptionMappers());
}
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import com.fasterxml.jackson.core.JsonParseException;
@Provider
public class JsonExceptionsMapper implements ExceptionMapper<JsonParseException> {
@Override
public Response toResponse(JsonParseException exception) {
//replace with your custom response
return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build();
}
}