【问题标题】:Spring Rest - bind nested DTO object to @RequestParamsSpring Rest - 将嵌套的 DTO 对象绑定到 @RequestParams
【发布时间】:2020-12-17 16:06:49
【问题描述】:

我想将 get 参数绑定到我的 DTO。我的问题是映射我的 DTO 拥有的嵌套列表。

控制器类:

@PostMapping(value = "test-endpoint")
public ResponseEntity<String> doStuff(@Valid @RequestParams MyDto myDto) {
    // do stuff
}

父级 DTO:

public class MyDto {
    @NotNull
    private String fieldA;

    @Valid
    @NotNull
    private List<MyNestedDto> nestedDto;
}

嵌套 DTO:

public class MyNestedDto {
    @NotNull
    private String nestedFieldA;

    @NotNull
    private String nestedFieldB;

    // more fields
}

我有一个向我的控制器发送 POST 请求的服务。请求无法更改,因此我无法使用 @RequestBody 注释。

请求如下所示:

http://localhost:8080/api/test-endpoint?nestedDto={"more":[{"nestedFieldA":"example","nestedFieldB":"example"}]}&fieldA=123

有没有办法绑定嵌套列表来获取参数?

编辑*

注册转换器好像不起作用,我的转换器转换方法甚至没有被调用。

@Configuration
public class WebConfiguration implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new MyConverter());
    }
}

public class MyConverter implements Converter<String, MyDto> {

    @Override
    public MyDto convert(String source) {
        // it never reaches there
        ObjectMapper objectMapper = new ObjectMapper();
        
        return null; // return null for testing purposes
    }
}

【问题讨论】:

  • 抱歉有什么问题?你想将该 JSON 映射到 @RequestParam
  • 是的,有没有办法在不更改请求的情况下将该 JSON 映射到 @RequestParam?
  • 使用PostMapping 或使用GetMappings ?
  • 你可以在我的控制器上看到它是 PostMapping
  • 为什么你使用POST 方法和GET 的语义做所有事情? POST 您的对象并从 @RequestBody 获取它或使用 GET 并独立接收每个参数或使用 Map。建议:使用POST/@RequestBody

标签: java spring rest


【解决方案1】:
public class AController {
     private final ObjectMapper objectMapper;
     private final Validator validator;

     public AController(ObjectMapper objectMapper,Validator validator){
          this.objectMapper = objectMapper;
          this.validator = validator;
     }

     @PostMapping(value = "test-endpoint")
     public ResponseEntity<String> doStuff(@RequestParam("nestedDto") String nestedDto) {
           MyDto myDto = objectMapper.readValue(nestedDto);
           Set<ConstraintViolation<MyDto>> constraintViolation = 
           validator.validate(myDto);
           if (!constraintViolation.isEmpty()) {
                throw new ConstraintViolationException(constraintViolation);
           }
     }

}

这是伪代码,所以我只是写它来演示如何解决问题。 如果你想要更优雅的方式,你必须改变请求,因为这里的请求是错误的。

【讨论】:

  • 感谢您的回答,我在发布此问题之前就知道此解决方案。正如我所说,我想知道是否有更优雅的方式来进行这种反序列化,因为在我的大多数控制器中这样做并不方便。
  • 我会检查一下谢谢,我正在考虑使用自定义转换器,但我似乎无法使其工作。
猜你喜欢
  • 1970-01-01
  • 2014-05-08
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 2019-04-01
  • 2017-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多