Джерси: возврат 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 для обоих.