JSON 은 REST 로 데이터를 서버로부터 받아올 때 가장 흔한 데이터 형태로
Android 에서는 이걸 파싱할 일이 정말 많은만큼 방법도 많다.
일단 대표적인 라이브러리로
- GSON
- Jackson
이렇게 두 가지가 있는데, 간단하게 둘을 비교하자면
Gson - 용량이 크지 않은 데이터 처리 작업에서 유리하고 가벼운 느낌이라면
Jackson - 대용량 데이터 처리에 강하고, 유연한 느낌이라고 할 수 있다(XML 도 지원한다)
오늘은 이 둘 중 Jackson Library 를 다뤄볼 것이다.
일단 오늘의 샘플 데이터다
const val SAMPLE = "[\n" +
" {\n" +
" \"id\": 111,\n" +
" \"name\": \"키보드\",\n" +
" \"descr\": \"일 할 때 바쁜 친구.\"\n" +
" },\n" +
" {\n" +
" \"id\": 222,\n" +
" \"name\": \"마우스\",\n" +
" \"descr\": \"키보드만큼 바쁜 친구\"\n" +
" },\n" +
" {\n" +
" \"id\": 333,\n" +
" \"name\": \"모니터\",\n" +
" \"descr\": \"사실 제일 바쁜데 조용한 친구\"\n" +
" }\n" +
"]"
data class Item(
@JsonProperty("id")
val id: Long,
@JsonProperty("name")
val name: String,
@JsonProperty("descr")
val description: String
)
Jackson Library 는 기본적으로 ObjectMapper 라는 것을 사용하고
이 ObjectMapper 를 이용해 객체를 JSON으로 직렬화하거나 JSON을 String 으로 역직렬화 할 수 있다.
그러면 일단 우리는 파싱이 주 목적이었으니 역직렬화를 먼저 해보자
역직렬화를 할 땐 ObjectMapper 가 우선 String 을 JsonNode 라는 객체로 바꾸는데
쉽게? 설명하자면 List나 map 처럼 바꾸는 것이다.
- JsonNode 안에 JsonNode 들이 들어있다
- 일반적으로 내 data Class(model class) 와 매핑시킨다고 생각하면 쉽다.
사실 코드를 보는게 이해가 더 쉬울 것 같다..
val objectMapper = ObjectMapper()
val dataNode: JsonNode = objectMapper.readTree(SAMPLE)
dataNode.forEach { node->
val item = objectMapper.treeToValue(node, Item::class.java)
println("이름: ${item.name}\n특징: ${item.description}")
}
이렇게 코드를 실행시키면?
2024-01-05 14:42:52.205 15095-15095/com.hl.test I/System.out: 이름: 키보드
2024-01-05 14:42:52.205 15095-15095/com.hl.test I/System.out: 특징: 일 할 때 가장 바쁜 친구.
2024-01-05 14:42:52.206 15095-15095/com.hl.test I/System.out: 이름: 마우스
2024-01-05 14:42:52.206 15095-15095/com.hl.test I/System.out: 특징: 키보드만큼 바쁜 친구
2024-01-05 14:42:52.207 15095-15095/com.hl.test I/System.out: 이름: 모니터
2024-01-05 14:42:52.207 15095-15095/com.hl.test I/System.out: 특징: 사실 제일 바쁜데 티는 조용한 친구
이런 결과를 얻어낼 수 있다.
반대로 직렬화 역시 가능하다
Item 이란 객체를 JSON으로 바꿔보자
val objectMapper = ObjectMapper()
val sampleItem = Item(
id = 444,
name = "에어팟",
description = "주인이 일할 땐 쉬는 친구"
)
val json = objectMapper.writeValueAsString(sampleItem)
println(json)
이 코드를 실행시키면?
2024-01-05 14:48:46.733 15861-15861/com.hl.test I/System.out: {"id":444,"name":"에어팟","description":"주인이 일할 땐 쉬는 친구"}
JSON 으로 직렬화가 되었다
지금은 샘플이고 내가 작성했기 때문에 별 다른 문제가 없지만 보통은 위 작업을 try-catch 블록으로 감싸주는데 그 것만으로는 해결이 안되는 예외가 있다.
- API 로 확인했던것 외의 프로퍼티가 추가로 오는 상황
- 와야할 프로퍼티 가 안 오는 상황
위 상황에선 crash 가 발생하는 경우도 있기 때문에 별도로 처리를 해줘야 하는데
기본적으로 1번의 경우 아래와 같이 작성해주면 쉽게 처리가 가능하다
@JsonIgnoreProperties(ignoreUnknown = true)
data class Item(
@JsonProperty("id")
...
대략 영어를 해석해보면 알 수 있듯이 모르는 프로퍼티 는 무시해버린다는 조건을 달아주는 것이다.
이러면 1번에 대한 예외는 끝났고 2번의 경우다.
@JsonIgnoreProperties(value = ["property_1", "property_2"], allowSetters = false)
data class Item(
@JsonProperty("id")
...
Jackson 에 매핑시키는 모델 클래스를 Java 로 구현해보면 기본적으로 Jackson 은
- JsonNode 의 각 값을
- model class
- 각 field에
- setter 로
달아주는 형태이다(그래서 Java 에선 getter/setter를 모두 작성해야 하고 프로퍼티가 많으면 별 내용도 없이 모델 클래스의 코드 길이가 엄청 길어진다)
그렇기 때문에 모르는 프로퍼티에 대해선 setter 를 허용하지 않는 조건까지 같이 달아줌으로써
2번에 해당하는 예외를 처리할 수 있다.
'Android > Kotlin' 카테고리의 다른 글
Android Room Database 사용하기 (1) | 2024.01.08 |
---|---|
Android ExoPlayer 로 앱에서 동영상 재생하기 (1) | 2024.01.05 |
Android 파일 다운로드 받기 (0) | 2024.01.05 |
Android Custom Dialog 만들기 (2) | 2024.01.04 |
[Kotlin] 문자열(String) 유사도 검사하기 - (1) (3) | 2024.01.03 |