개요
Retrofit2를 활용할 시 보통 대부분 응답 결과가 JSON으로 오기 때문에 GsonConverter를 사용한다. 하지만 국내 일부 공공데이터나 오래된 데이터는 XML 결과만 제공한다. 아래 '국문 관광정보 서비스'가 대표적이다.
과거에는 SimpleXML 라이브리를 활용하여 Converting이 가능했다고 하는데 현재는 deprecated되어 사용 불가능한 상태이다. 구글링한 결과 Tikxml이 가장 괜찮은 라이브러리로 보여 사용법을 소개한다.
종속성 추가
//retrofit
implementation "com.squareup.retrofit2:retrofit:2.7.2"
//xml parser
implementation 'com.tickaroo.tikxml:annotation:0.8.13'
implementation 'com.tickaroo.tikxml:core:0.8.13'
implementation 'com.tickaroo.tikxml:retrofit-converter:0.8.13'
kapt 'com.tickaroo.tikxml:processor:0.8.13'
만약 kotlin-kapt 플러그인을 사용하고 있지 않다면 기존 annotationProcessor 활용할 것
RetrofitClient 작성
object RetrofitClient {
private var instance: Retrofit? = null
fun getInstance(): Retrofit {
if (instance == null)
instance = Retrofit.Builder()
.baseUrl("http://api.visitkorea.or.kr/openapi/service/rest/KorService/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(TikXmlConverterFactory.create(TikXml.Builder().exceptionOnUnreadXml(false).build()))
.build()
return instance!!
}
}
눈 여겨 볼 곳은addConverterFactory(TikXmlConverterFactory.create(TikXml.Builder().exceptionOnUnreadXml(false).build())) 이다.
기존 GsonConverterFactory.create() 대신 추가된 모습이다. 하나 또 주목할 점은 TikXml.Builder().exceptionOnUnreadXml(false).build() 이 코드 부분인데, xml을 읽는 과정에서 POJO 클래스에서 굳이 읽고 싶지 않은 데이터가 있을 경우 추가해주는 것이 좋다. 없다면 에러가 발생함.
다음으로 POJO를 작성하기 전에 아래와 같은 반환결과가 온다고 가정하자.
위를 기반으로 POJO 클래스를 작성해본다면, 아래와 같다.
@Xml(name="response")
data class Tour(
@Element
val header: Header,
@Element
val body: Body,
){
}
@Xml(name = "header")
data class Header(
@PropertyElement
val resultCode: Int,
@PropertyElement
val resultMsg: String,
)
@Xml(name = "body")
data class Body(
@Element
val items: Items,
@PropertyElement
val numOfRows: Int,
@PropertyElement
val pageNo: Int,
@PropertyElement
val totalCount: Int,
)
@Xml
data class Items(
@Element(name = "item")
val item: List<Item>
)
@Xml
data class Item(
@PropertyElement(name="addr1") var address: String?,
@PropertyElement(name="contenttypeid") var contentTypeId : Int?,
@PropertyElement(name="mapx") var latitude : Double?,
@PropertyElement(name="mapy") var longitude : Double?,
@PropertyElement(name="tel") var tel: String?,
@PropertyElement(name="title") var title: String?,
@PropertyElement(name="firstimage") var mainImageUrl: String?,
@PropertyElement(name="firstimage2") var subImageUrl: String?
){
constructor() : this(null,null,null,null,null,null,null,null)
}
@Xml은 하위 Element를 감싸는 annotation이고, Element는 그 다음 하위, PropertyElement는 Element 내부 property들을 의미한다. 이에 대한 아주 자세한 설명은 아래 wiki에 설명되어있다.
위에서 주목할 점은 필드가 모두 Nullable처리가 되어있다는 점이다. 만약 XML에서 받으려고 했던 일부 프로퍼티가 존재하지 않을 경우 null로 받을 수 있도록 처리해야되기 때문이다.
'안드로이드' 카테고리의 다른 글
[Android] Dagger2를 활용한 Dependency Injection (0) | 2021.04.26 |
---|---|
[Android] MVVM, RxJava, Paging 활용한 리스팅 (0) | 2021.03.11 |
[Android] Custom Titlebar를 fragment로 만들기 (0) | 2021.03.04 |
안드로이드 개발만 진행하던 사람의 Flutter 사용 후기 (0) | 2021.01.12 |
[Android] 카카오 로그인(v2) 구현 가이드 (0) | 2020.12.29 |