티스토리 뷰
json 문자열을 자바 객체로 역직렬화(deserialization)하거나 반대로 자바 객체를 json 문자열로 직렬화(serialization)을 할때 자바 라이브러리로는 대표적으로 jackson을 많이 사용한다. 직렬-역직렬시 json key를 결정하는건 @JsonProperty 라는 애노테이션을 이용한다.
public class TestClass{
@JsonProperty("name")
private String name;
}
TestClass 객체를 직렬화하거나 혹은 json 문자열을 TestClass 객체로 역직렬화시 name key는 @JsonProperty 애노테이션에 name으로 지정된 곳에 매핑이 되게된다. 참고로 해당 애노테이션이 없을때는 기본적으로 필드명끼리 매핑시키므로 예제와같이 필드명과 동일할 경우엔 굳이 명칭을 맞춰주고자 @JsonProperty 애노테이션을 달필요는 없다.
1. 이슈
예제 코드를 바탕으로 생각할때 name key는 name 필드에 매핑되게된다.
public class DeserializeTest {
private ObjectMapper objectMapper;
@Before
public void setUp(){
this.objectMapper = new ObjectMapper();
}
@Test
public void test() throws IOException {
String json = "{\"name\":\"hello world\"}";
TestClass result = this.objectMapper.readValue(json, TestClass.class);
assertThat(result.getName(), is("hello world"));
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class TestClass{
@JsonProperty("name")
private String name;
}
}
지금과 같은 테스트케이스에서 json 변수에 들어있는 문자열을 역직렬화시 정상적으로 테스트케이스를 성공하는걸 볼 수 있다. 하지만 이번에 생긴 이슈는 json 필드가 여러개일때다. 이런 테스트 케이스를 떠올리면 될 것 같다.
@Test
public void test() throws IOException {
List<String> jsons = Arrays.asList("{\"name1\":\"hello world\"}",
"{\"name2\":\"hello world\"}",
"{\"name3\":\"hello world\"}");
for(String json : jsons){
TestClass result = this.objectMapper.readValue(json, TestClass.class);
assertThat(result.getName(), is("hello world"));
}
}
key 명칭만 다르지 들어가는 데이터 유형엔 다른것이 없기때문에 역직렬화를 위한 클래스를 추가하는건 매우 비효율적인것 같다. 하지만 @JsonProperty 애노테이션의 인자는 정규표현식을 받거나, 여러 key를 받아주지않는다.
2. Jackson 2.9 - @JsonAlias
릴리즈 된지 얼마 되지않은 Jackson 2.9 버전에서 새로이 추가된 @JsonAlias 애노테이션이 저 이슈를 완벽히 해결해준다.
public class DeserializeTest {
private ObjectMapper objectMapper;
@Before
public void setUp(){
this.objectMapper = new ObjectMapper();
}
@Test
public void test() throws IOException {
List<String> jsons = Arrays.asList("{\"name1\":\"hello world\"}",
"{\"name2\":\"hello world\"}",
"{\"name3\":\"hello world\"}");
for(String json : jsons){
TestClass result = this.objectMapper.readValue(json, TestClass.class);
assertThat(result.getName(), is("hello world"));
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class TestClass{
@JsonAlias({"name1", "name2", "name3"})
private String name;
}
}
테스트 케이스를 실행해보면 아무문제없이 정상적으로 성공하는걸 볼 수 있다. 다만 이 포스팅을 작성하는 현 시점에서 기본적으로 Jackson 의존성을 갖고있는 최신 스프링부트가 아직 2.8 버전을 사용하고있다. 2.9 버전을 사용하기위해선 직접 의존성을 추가해줘야한다.
그래들을 사용하고있다면 이런식으로 의존성을 추가해주면 된다.
dependencies {
compile('org.springframework.boot:spring-boot-starter-web'){
exclude(module: 'jackson-databind')
}
compile('com.fasterxml.jackson.core:jackson-databind:2.9.3')
compile('com.fasterxml.jackson.core:jackson-annotations:2.9.3')
compile('com.fasterxml.jackson.core:jackson-core:2.9.3')
compile('org.projectlombok:lombok')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
'Java' 카테고리의 다른 글
log4j2 프로젝트에 log4j 라이브러리 사용시 충돌 (0) | 2018.02.05 |
---|---|
Jackson 2.9.1~2.9.3 @JsonProperty 버그 (0) | 2018.01.13 |
역어셈블리 (0) | 2018.01.07 |
Builder Pattern (0) | 2017.12.31 |
Jackson Serialize 시 클래스 정보가 필요할때 (0) | 2017.12.28 |
- Total
- Today
- Yesterday
- code
- go-core
- spring cloud
- MySQL
- toby
- EffectiveJava
- frontcode
- 정규표현식
- JPA
- generics
- TEST
- java8
- Git
- db
- servlet
- Spring
- java
- Kotlin
- javascript
- clean code
- JavaScript Core
- backend개발환경
- frontend개발환경
- mariadb
- DesignPattern
- Jackson
- programming
- Design Pattern
- http
- OOP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |