簡體   English   中英

在 ControllerAdvice 方法參數驗證 (@Valid) 響應中返回 @JsonAlias 值

[英]Return @JsonAlias value in ControllerAdvice Method Argument Validation (@Valid) response

我已經使用最新版本的 javax.validation 實現了一個簡單的驗證。

所以我的課:

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Person {

    @NotNull(message = "Required field")
    @JsonAlias(value = "current_name")
    private String name;

    @NotNull(message = "Required field")
    private String age;
}

然后我創建了一個 Advice 來處理和自定義異常消息。 像這樣:

@ControllerAdvice
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex,
            HttpHeaders headers,
            HttpStatus status,
            WebRequest request) {

        List<FieldError> errors = ex.getBindingResult().getFieldErrors();

        List<Field> listOfErrors = errors.stream()
                .map(error -> Field.builder()
                        .field(error.getField())
                        .message(error.getDefaultMessage())
                        .build())
                .collect(Collectors.toList());

        ApiError apiError = new ApiError("validation_error", "Some invalid fields", listOfErrors);
        return handleExceptionInternal(ex, apiError, headers, HttpStatus.BAD_REQUEST, request);
    }
}

因此,當獲取error.getField() 時,它是原始屬性名稱:“name”。 但我需要獲取別名:“current_name”。

我正在使用傑克遜庫。

這是可能的?

在您的 handleMethodArgumentNotValid 方法中,執行以下操作

  1. 查找當前參數類型的所有字段
    Field[] clsFields = ex.getParameter().getParameter().getType().getDeclaredFields();
  1. 在該字段上查找匹配的 Field 和 @JsonAlias 注釋

  2. 讀取注釋的值 --> 這是您輸入的值

 @JsonAlias(value = "current_name")
 String name;
  1. 使用該值而不是原始字段error.getField()

完整的工作示例:

import com.fasterxml.jackson.annotation.JsonAlias;
import lombok.*;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.*;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.*;

@SpringBootApplication
public class JsonInspect {
    public static void main(String[] args) { SpringApplication.run(JsonInspect.class, args); }
}
@RestController
class Controller {
    @PostMapping("/test")
    public void t(@RequestBody @Valid Person p) {
        System.out.println(p);
    }
}
@ControllerAdvice
class CustomRestExceptionHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

        Field[] clsFields = ex.getParameter().getParameter().getType().getDeclaredFields();

        List<FieldError> errors = ex.getBindingResult().getFieldErrors();

        List<ErrField> listOfErrors = errors.stream()
                .map(e -> new ErrField(getJsonAlias(clsFields, e), e.getDefaultMessage()))
                .collect(Collectors.toList());

        ApiError apiError = new ApiError("validation_error", "Some invalid fields", listOfErrors);
        return handleExceptionInternal(ex, apiError, headers, HttpStatus.BAD_REQUEST, request);
    }

    String getJsonAlias(Field[] clsFields, FieldError e) {

        JsonAlias[] alisas = getAnnotationsForField(clsFields, e.getField());
        if (alisas == null || alisas.length == 0) {
            return e.getField();
        }

        String[] values = alisas[0].value();
        if (values.length == 0) {
            return e.getField();
        }

        return values[0];
    }
    JsonAlias[] getAnnotationsForField(Field[] clsFields, String fieldName) {
        Optional<Field> first = Stream.of(clsFields).filter(f -> f.getName().equals(fieldName)).findFirst();
        return first.map(field -> field.getAnnotationsByType(JsonAlias.class)).orElse(null);
    }

}

@Data
@AllArgsConstructor
class ErrField {
    String fld;
    String message;
}
@Data
@AllArgsConstructor
class ApiError {
    String type;
    String message;
    List<ErrField> fields;
}
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Data
class Person {
    @JsonAlias("person_name")
    @NotNull
    String name;
    @NotNull
    String address;
}

所需的庫

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM