제네릭 DTO Jackson으로 추출하기 - PEACH-BROS/lets-merge GitHub Wiki

public class StandardResponse<T> {
    private T data;

    private StandardResponse() {
    }

    public StandardResponse(T data) {
        this.data = data;
    }

    public static <T> StandardResponse<T> of(T data) {
        return new StandardResponse<>(data);
    }

	...

    public T getData() {
        return data;
    }
}

위와 같은 통일된 Response클래스를 사용할 때 아래와 같이 Controller에서 반환합니다.

	// in Controller.class
	@ResponseStatus(HttpStatus.OK)
    @GetMapping
    public StandardResponse<MissionsResponse> showMissions() {
        return StandardResponse.of(missionService.showMissions());
    }

이런 제네릭한 Response들을 Jackson으로 추출하기 위해서는 언제나 해왔듯 아래와 같이 추출한다.

StandardResponse<MissionsResponse> missionsResponseStandardResponse = objectMapper.readValue(result,StandardResponse.class);

그럼 ClassCastException이 발생하게 된다. 이는 제네릭타입은 런타임에 타입 정보가 소거되는 실체화 불가 타입이기 때문이다.

이를 해결하기 위해 우리는 super type token을 사용해야하는데 jackson에서는 TypeReference이고 spring에서는 ParamerterizedTypeReference를 사용한다.

아래와 같이 작성하면 해결할 수 있다.

StandardResponse<MissionsResponse> missionsResponseStandardResponse
                = objectMapper.readValue(result, new TypeReference<StandardResponse<MissionsResponse>>() {});