【问题标题】:@JsonView on Spring @GetMapping query parameter objects@JsonView on Spring @GetMapping 查询参数对象
【发布时间】:2022-01-24 22:08:46
【问题描述】:

在 Spring 中,是否可以在 URL 查询参数对象上使用 @JsonView?我可以为@RequestBody 做这件事,但我们在 GET 请求中没有正文。本题专门针对已经被Spring转为对象的URL查询参数。

例如,我想要一个具有此映射的控制器:

@GetMapping("/user") 
ResponseEntity<UserDTO> searchUser(@JsonView(value = UserView.Searchable.class) UserDTO userQuery) {
    //Do some work here using userQuery object for searching users
    return ResponseEntity.ok();
}

UserDTO:

public class UserDTO {
    
    @JsonProperty("id")
    @JsonView(UserView.Private.class)
    private String id= null;

    @JsonView(UserView.Searchable.class)
    @JsonProperty("city")
    private String city = null;

    @JsonProperty("country")
    @JsonView(UserView.Searchable.class)
    private String country = null;

    @JsonProperty("state")
    private String state = null;

    @JsonProperty("zipCode")
    private String zipCode = null;
    
    //More properties and getter/setters...etc
}

因此,如果我想调用端点,我可以创建一个类似的 URL localhost:8080//api/user?country=Canada 在加拿大搜索用户,但如果我尝试localhost:8080//api/user?id=123,该属性将被忽略。

编辑: 我可能仓促地提出了这个想法。 url 参数没有 JSON 反序列化,因为它们不是 JSON。 Spring 从ServletModelAttributeMethodProcessor 创建查询对象。也许如果我想要一些自定义行为,我需要实现 HandlerMethodArgumentResolver 并自己做。

编辑 2 我对 Spring 有点陌生,所以我有很多东西要学,但我认为我要做的就是使用 @InitBinder 将绑定字段列入白名单

@InitBinder
public void setSearchableFields(WebDataBinder binder) {
    binder.setAllowedFields(
            "city",
            "country"
            );
}

【问题讨论】:

  • 在我看来,这使代码更难阅读。只需创建一个新的UserSearchDto,其中仅包含对给定端点有效的属性。重用代码只在某些时候有用,有时更明确。

标签: java spring spring-mvc jackson


【解决方案1】:

在我的一个项目中,我将 POJO 用于查询参数。我怀疑春季默认情况下会忽略任何属性,您可以忽略空检查。

QueryParams.java

@Data
public class QueryParams {

    Integer page;
    Integer pageSize;
    String sortBy;
    Sort.Direction direction;
    String searchId;
    String status;
    String symbol;

    public PageRequest getPageRequest(){
        if(this.page==null){
            this.page = 0;
        }

        if(this.pageSize==null){
            this.pageSize = 25;
        }

        if(this.sortBy==null){
            this.sortBy = "createdAt";
        }

        if(this.direction ==null){
            this.direction = Sort.Direction.DESC;
        }

        return PageRequest.of(this.page, this.pageSize, Sort.by(this.direction, this.sortBy));
    }

}

还有我的控制器:

@GetMapping("currencies")
public ResponseEntity<Page<CurrencyConfig>> getAllCurrencies(@Valid QueryParams queryParams) {

    try {
        return ResponseEntity.ok(orderbookService.getAllCurrencyConfig(queryParams));
    } catch (HttpClientErrorException | HttpServerErrorException e) {
        throw new ResponseStatusException(e.getStatusCode(), e.getMessage());
    } catch (Exception e) {
        e.printStackTrace();
        throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR,
            e.getLocalizedMessage());
    }


}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 2019-07-27
    • 2022-01-18
    • 2013-09-29
    • 2017-11-14
    相关资源
    最近更新 更多