0

I want to bind get params to my DTO. My problem is mapping the nested list my DTO has.

controller class:

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

parent DTO:

public class MyDto {
    @NotNull
    private String fieldA;

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

Nested DTO:

public class MyNestedDto {
    @NotNull
    private String nestedFieldA;

    @NotNull
    private String nestedFieldB;

    // more fields
}

I have a service that sends a POST request to my controller. The request cannot be changed hence why I can't use @RequestBody annotation.

The request looks like that:

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

Is there a way to bind the nested list to get params?

Edit*

Registering a converter doesn't seem to work, my converter convert method is not even called.

@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
    }
}
Thanos M
  • 604
  • 6
  • 21
  • sorry what is problem ? do you want to map that JSON to `@RequestParam` – Ryuzaki L Dec 14 '20 at 16:15
  • yes is there a way to map that JSON to @RequestParam without changing the request? – Thanos M Dec 14 '20 at 16:19
  • with the `PostMapping` or using `GetMappings` ? – Ryuzaki L Dec 14 '20 at 16:22
  • you can see it on my controller it's PostMapping – Thanos M Dec 14 '20 at 16:23
  • Why you use `POST` method and the do everything on semantics of `GET`? Either `POST` your object and get it from `@RequestBody` or use `GET` and receive each params independently or use Map. Recommendation: Use `POST/@RequestBody`. – Rana_S Dec 14 '20 at 18:49
  • I cannot use @RequestBody because as I said I cannot modify the incoming request that is being made to my controller. – Thanos M Dec 14 '20 at 19:11
  • The main problem is not the request method but how to bind my nested dto to get params as described – Thanos M Dec 14 '20 at 19:15
  • Bind HttpServletRequest to controller method then get parameters and use objectMapper to convert it to object – Gurkan İlleez Dec 14 '20 at 19:22
  • I would prefer a more elegant way, I want to avoid deserializing those params inside my controller manually. Doing that in most of my controllers is not the way to go in my opinion. – Thanos M Dec 14 '20 at 19:24

1 Answers1

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);
           }
     }

}

This is pseudo code so i just write it to demonstrate how to solve the problem. If you want more elegant way, you have to change request because request is wrong here.

Gurkan İlleez
  • 1,503
  • 1
  • 10
  • 12
  • Thank you for your answer, I was aware of this solution before posting this question. As I said I would like to know if there is a more elegant way of doing this deserialization since it's not convenient doing that in most of my controllers. – Thanos M Dec 14 '20 at 19:35
  • https://stackoverflow.com/questions/38360215/how-to-create-a-spring-interceptor-for-spring-restful-web-services – Gurkan İlleez Dec 14 '20 at 19:42
  • I ll check it out thanks, I was thinking of using a custom converter but I don't seem to be able to make it work. – Thanos M Dec 14 '20 at 19:44