Весенняя загрузка кастомного десериализатора - PullRequest
0 голосов
/ 20 января 2020

У меня есть API для отдыха, который имеет 3 поля ввода, а именно EmployeeId, isActive и Name. EmployeeId определен как Long, isActive как логическое значение и имя как String. Мне нужно знать, когда кто-то передает недопустимые значения для этих полей, например: alphanumeri c значение для employeeId (число), как бы я обработал это и представил пользовательское сообщение об ошибке, говорящее «EmployeeId может быть только числом и должно иметь от 8 до 11 цифры "?

Я пытался определить пользовательский десериализатор и создать ControllerAdvice, но он не сработал. Ниже приведены классы.

JSON RequestDTO:

public class Address implements Serializable {

    private static final long serialVersionUID = -1946551108793695733L;

    @JsonDeserialize(using = NumberDeserializer.class)
    @JsonSerialize(using =NumberSerializer.class)
    private Long employeeId;

    private Boolean isManager;

    private String name;

    //getters and setters
}
-----------------------------------------------------------------------------
Custom ControllerAdvice implelementation:`enter code here`

public class CustomControllerAdvice extends ResponseEntityExceptionHandler {

      //other exception handlers
    private static final String STRING_CONSTANT_VALIDATION_ERRORS = "Validation errors";
    private static final String STRING_CONSTANT_APPLICATION_ERRORS = "Some error occured while processing the request. Please reach out to the customer service."; 

       @ExceptionHandler(DateFormatException.class)
       @ResponseBody
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       public ResponseEntity<Object> handleDateFormatException(
               DateFormatException ex) {
           log.info("handling exception for DateFormatException");
           ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, STRING_CONSTANT_VALIDATION_ERRORS);
           apiError.setMessage(ex.getMessage());
           return buildResponseEntity(apiError);
       }

       @ExceptionHandler(DateTimeFormatException.class)
       @ResponseBody
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       public ResponseEntity<Object> handleDateTimeFormatException(
               DateFormatException ex) {
           log.info("handling exception for DateTimeFormatException");
           ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, STRING_CONSTANT_VALIDATION_ERRORS);
           apiError.setMessage(ex.getMessage());
           return buildResponseEntity(apiError);
       }

       @ExceptionHandler(NullPointerException.class)
       @ResponseBody
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       public ResponseEntity<Object> handleNullPointerException(
               DateFormatException ex) {
           log.info("handling exception for DateTimeFormatException");
           ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, STRING_CONSTANT_APPLICATION_ERRORS);
           apiError.setMessage(ex.getMessage());
           return buildResponseEntity(apiError);
       }

       @ExceptionHandler(InvalidNumberException.class)
       @ResponseBody
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       public ResponseEntity<Object> handleInvalidNumberException(
               DateFormatException ex) {
           log.info("handling exception for DateFormatException");
           ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, STRING_CONSTANT_VALIDATION_ERRORS);
           apiError.setMessage(ex.getMessage());
           return buildResponseEntity(apiError);
       }

       @ExceptionHandler(Exception.class)
       @ResponseBody
       @ResponseStatus(HttpStatus.BAD_REQUEST)
       public ResponseEntity<Object> handleAnyOtherException(
               DateFormatException ex) {
           log.info("handling any other type of exception");
           ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, STRING_CONSTANT_VALIDATION_ERRORS);
           apiError.setMessage(ex.getMessage());
           return buildResponseEntity(apiError);
       }

       private ResponseEntity<Object> buildResponseEntity(ApiError apiError) {
           return new ResponseEntity<>(apiError, apiError.getStatus());
       }

}

-----------------------------------------------------------------------------
Desrializer implementation

public class NumberDeserializer extends JsonDeserializer<Long> {

    @Override
    public Long deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonToken currentToken = jp.getCurrentToken();
        boolean errorOccured = false;
        Long retVal = 0l;
        log.info("Inside the NumberDeserializer, supplied value being null? {}", currentToken == null || StringUtils.isBlank(currentToken.asString()));
        if (currentToken == null || JsonToken.VALUE_NULL.equals(currentToken)) {
            log.info("inside null");
            retVal = null;
        }
        else if (!StringUtils.isBlank(currentToken.asString())) {
            try {
                log.info("inside not null");
                retVal = Long.parseLong(currentToken.asString());
            }catch(NumberFormatException nfe) {
                errorOccured = true;
                log.error("JSON desrialization error: invalid mumber "+currentToken.asString());
            }
            if(errorOccured) {
                log.info("throwing the InvalidNumberFormatException for supplied value {}", currentToken.asString());
                throw new InvalidNumberException("Invalid value "+ currentToken.asString()+" being passed for a numeric value");
            }
        }
        log.info("return");
        return retVal;
    }

}

-----------------------------------------------------------------------------
Serializer Implementation:

@Slf4j
@JsonComponent
public class NumberSerializer extends JsonSerializer<Long> {

    @Override
    public void serialize(Long value, JsonGenerator jgen, SerializerProvider arg2) throws IOException {
        log.info("inside the serializer start. Value being {}", value);
         try {
             if (value == null) {
                 jgen.writeNull();
             }
             else {
                 jgen.writeString(value.toString());
             }
         }catch (Exception e){
            log.info("inside the serializer catch block");
            jgen.writeString(StringUtils.EMPTY);
             e.printStackTrace();
         }
            log.info("inside the serializer end");
    }

-----------------------------------------------------------------------------

ApiError - это пользовательский класс для инкапсуляции сведений (httpStatus, сообщение об ошибке) для отправки в ответ.

В настоящее время я вижу только Http 400 в ответе с пустым содержимым:

Response Code
400
Response Headers
{
  "content-length": "0",
  "date": "Mon, 20 Jan 2020 15:44:14 GMT",
  "content-type": null
}
...