일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 스프링
- devcamp
- 인프런
- 쿼리
- java
- MySQL
- Oracle
- 자바문제
- 오라클
- 기초쿼리
- 자바기초
- 스프링의정석
- mariadb
- 국비지원
- 자바연습문제
- RDBMS
- 자바
- cleanbuild
- 자바의정석
- oauth
- 남궁성
- 불친절한SQL
- 패스트캠퍼스
- SpringFramework
- 클린빌드
- 패캠
- 소셜로그인
- SQL
- ApplicationContext
- Spring
- Today
- Total
Darren's Devlog
[ObjectMapper] CustomDeserializer 만들기 본문
ObjectMapper은 데이터 포맷 중 하나인 JSON을 간편하게 POJO로 다룰 수 있는 기능들을 제공합니다.
또한 매우 Customizable하기 때문에 고도한 Object 처리를 가능하게 해줍니다.
오늘은 JSON → POJO로 변환하는 과정(Deserialize, 역직렬화)에서 발생한
InvalidFormatException을 해결할 수 있는 CustomDeserializer클래스를 만들어보겠습니다.
1. 시나리오
Book JSON
[
{
"name":"자바의정석",
"reviewCount":"735"
},
{
"name":"토비의스프링",
"reviewCount":"2,413"
}
]
BookDto
@Getter
@Setter
public class BookDto {
private String name;
private int reviewCount;
}
Service
@Service
@RequiredArgsConstructor
public class BookService {
private final ObjectMapper objectMapper;
public List<BookDto> getBooks(JsonNode responseNode) throws JsonProcessingException {
List<BookDto> bookList = objectMapper.readValue(responseNode.toString(), new TypeReference<List<BookDto>>() {});
return bookList;
}
}
Book JSON이 담긴 responseNode를 List<BookDto>로 변환해주는 코드입니다.
"자바의정석" 데이터의 경우 BookDto로 변환하는데 문제가 없지만,
"토비의스프링" 도서 데이터처럼 콤마(comma)를 포함하는 경우엔 BookDto로 변환이 불가능합니다.
형변환 에러 로그
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.lang.Integer` from String "2,413": not a valid `java.lang.Integer` value
reviewCount는 엄연한 숫자 데이터이지만, 위처럼 변환이 불가능한 경우에는
CustomDeserializer 클래스를 정의하여 등록해주면 ObjectMapper를 보다 유용하게 사용 가능합니다.
2. 구현 코드
CustomIntegerDeserializer
public class CustomIntegerDeserializer extends JsonDeserializer<Integer> {
@Override
public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
String stringNumber = p.getValueAsString();
if(Objects.isNull(stringNumber) || "".equals(stringNumber)) return null;
return Integer.parseInt(stringNumber.replace(",", ""));
}
}
JsonDeserializer를 상속받아 deserialize메서드를 오버라이딩하는 커스텀 클래스를 만들어줍니다.
콤마를 stringNumber.replace(",", "")로 변환 후, Integer.parseInt()를 통해 int형으로 반환합니다.
BookDto
@Getter
@Setter
public class BookDto {
private String name;
private int reviewCount;
}
reviewCount의 타입을 기본형 int에서 Wrapper클래스인 Integer로 변경해줍니다.
기본형 int타입의 경우 의도한대로 변환이 불가능합니다.
ObjectMapper
@Configuration
public class SpringConfig {
@Bean
public ObjectMapper objectMapper() {
return JsonMapper.builder()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.addModule(new SimpleModule().addDeserializer(Integer.class, new CustomIntegerDeserializer()))
.build();
}
}
위 코드처럼 CustomIntegerDeserializer 클래스를 module로 추가해주면
선언된 타입이 Integer일 때, 역직렬화 과정에서 CustomIntegerDeserializer 클래스에 의해 변환이 이루어집니다.
'Spring' 카테고리의 다른 글
[OAuth 2.0] 스프링부트로 Google 로그인 구현해보기 -2 (20) | 2023.01.14 |
---|---|
[OAuth 2.0] 개념과 Google OAuth2.0 세팅부터 스프링부트로 구현-1 (3) | 2022.12.27 |