Джерси: возврат 400 ошибок вместо 500 при получении недопустимого тела запроса
Я использую встроенную обработку Jackson для преобразования входящего JSON в POJO, например:
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response newCustomer( CustomerRepresentation customer)
{
...
}
Если клиент отправляет JSON с недопустимыми полями, Джерси в настоящее время возвращает 500 Internal Server Error
. Вместо этого я хотел бы вернуть 400 Bad Request
, желательно с некоторыми значимыми деталями, указывающими, какие поля находятся в ошибке.
Можно ли понять, как это можно сделать? (По крайней мере, возвращая общее 400 вместо полностью неулокального 500?)
Update:
Здесь исключение создается серверной стороной, до вызова моего обработчика:
javax.servlet.ServletException: org.codehaus.jackson.map.exc.UnrecognizedPropertyException:
Unrecognized field "this_isnt_a_known"_field" (Class com.redacted....), not marked as ignorable
Ответы
Ответ 1
Наконец-то я смог обойти эту проблему, реализовав ExceptionMapper
, чтобы поймать UnrecognizedPropertyException
, выброшенную Jackson, и сопоставить ее с ответом 400 Bad Request:
@Provider
public class UnrecognizedPropertyExceptionMapper implements ExceptionMapper<UnrecognizedPropertyException>
{
@Override
public Response toResponse(UnrecognizedPropertyException exception)
{
return Response
.status(Response.Status.BAD_REQUEST)
.entity( "'" + exception.getUnrecognizedPropertyName() + "' is an unrecognized field.")
.type( MediaType.TEXT_PLAIN)
.build();
}
}
Ответ 2
В земле капельницы есть ExceptionMapper
, называемый JsonProcessingExceptionMapper, который имеет аналогичную функциональность в отношении того, что вы ищете. Возможно, вы можете использовать это для вдохновения в том, как решить вашу конкретную проблему в мире, отличном от dropwizard.
Ответ 3
У меня была такая же проблема... К сожалению, нет хорошего способа, который я знаю, чтобы перехватить исключение Джексона и создать собственный код ошибки.
Один из вариантов - использовать @JsonIgnoreProperties
, а затем строго проверить десериализованный объект. Это не скажет вам, отправлен ли отправитель нежелательной, но если они пропустили обязательные поля, вы поймете это.
Я не могу найти способ доступа к фактическому JSON, переданному, кроме создания класса @Provider для захвата JSON, проверки его, а затем передать его Jackson для десериализации.
Ответ 4
Я попытался сопоставить статус 500 с статус 400 с ответом HolySamosa, но исключение не было захвачено этим преобразователем, а статус 500 возвращается.
После отладки я обнаружил, что JsonParseException бросается, а не UnrecognizedPropertyException. Это потому, что я отправлял некоторый текст мусора (это не был JSON вообще).
Когда я отправил правильный JSON с клиентской стороны, с форматом, который не был подходящим для моего DTO на стороне сервера, я получил UnrecognizedPropertyException.
Для этого есть два случая:
- когда вы отправляете мусор, который не является JSON, и
- при отправке JSON, но это не соответствует вашему классу DTO.
Теперь я возвращаю статус 400 для обоих.