Backend/개발

[Spring Boot] List의 null 값 처리하기1 - CustomConverter로 @RequestParam

지수쓰 2022. 4. 7. 17:18
반응형

요청이 컨트롤러에게 전해질 때 HandlerAdapter -> ArgumentResolver -> Handler(Controller)로 전해지는데
이때 ArgumentResolver에서 Converter를 사용해서 값을 변경한다.

@RequestParam으로 값을 받아올 때 ", "로 구분하면 List로 받아와 지는 것도 StringToCollectionConverter에서 변환이 이뤄지기 때문이다.

    public ResponseEntity<GameRecordResponseDto> result(
            @RequestParam(required = false) List<String> searchNames,
            @RequestParam(required = false) List<GameTypeCode> gameTypes) {

        // 빈 값 들어올 경우
        if (searchNames != null) {
            searchNames = searchNames.stream()
                    .filter(sn -> sn != null && !sn.equals(""))
                    .collect(Collectors.toList());
            if (searchNames.size() == 0) searchNames = null;
        }
        if (gameTypes != null) {
            gameTypes = gameTypes.stream()
                    .filter(gt -> gt != null && !gt.equals(""))
                    .collect(Collectors.toList());
            if (gameTypes.size() == 0) gameTypes = null;
        }

        if (searchNames != null && gameTypes != null) {
         } else if (searchNames != null && gameTypes == null) {
        } else if (searchNames == null && gameTypes != null) {
        }
}

List <String>, List <GameTypeCode>로 받아오는 파라미터가 있는데 만약에 클라이언트 쪽에서 실수로 "name1,, name2"로 보내버리면 중간에 null인 값이 리스트에 추가돼버려서 이걸 제거하는 처리를 컨트롤러 코드마다 해줬는데 컨버터를 이용해서 일괄적으로 처리할 수 있는 방법을 찾아봤다.

@Component
public class StringToListConverter implements Converter<String, List<?>> {
    @Override
    public List<?> convert(String source) {

        List<?> list = Arrays.asList(source.split(",")).stream()
                .filter(sn -> sn != null && !sn.equals(""))
                .collect(Collectors.toList());

        return list.size()==0 ? null : list;
    }
}

 

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

이렇게 Converter를 구현해서 설정해주면 된다!
",,,," 로 입력하면 List <String>에 null이 5개 들어가는 게 아니고 null이 반환되도록 해주었다.



근데 그냥 빈 값을 같은 이름으로 여러번 담아서 요청 보내게 되면 이거는 또 ArrayToListConverter와 같은 형식으로 구현해줘야 한다,,

public class ArrayToListConverter implements Converter<String[] , List<Long>> {
    @Override
    public List<Long> convert(String[] source) {
        if(source == null || source.length ==0 ) return null;
        List<Long> list = new ArrayList<>();
        for(int i=0; i<source.length; i++){
            if(source[i].isEmpty() || source[i]==null) continue;
            list.add(Long.valueOf(source[i]));
        }
        return list.isEmpty() ? null : list;
    }
}

이렇게 하는 건 뭔가 이 정도까지 추가할 건 아닌 것 같아서 @RequestParam List <@NotBlank String> 정도의 처리를 해주어야겠다.
지금 하려는 처리는 빈 값이 들어오는 걸 무시하도록 하는 목적이어서 converter를 사용해봤는데 List로 된 값에 대해 검증이 필요하다면 커스텀 validator를 만들어서 (Collection Validation 검색) 처리해도 좋을 것 같다.

추가) Enum에 올바른 값이 입력으로 왔는지는 List에 담아버리면 검증이 안돼서 다른 처리를 해줘야 할 것 같다..

 

Is it possible to split request params in Spring controllers?

I have a request like: example.com/search?sort=myfield1,-myfield2,myfield3 I would like to split those params to bind a List<String> sort in my controller or List<SortParam> where Sor...

stackoverflow.com