Retrofit으로 서버에 필요한 데이터를 요청한다. 데이터를 응답받을 때 응답 받은 데이터 중 필요한 데이터만 사용하고 싶은 경우가 있다. 예로 살펴보자.
{
"coord": {
"lon": 129.3343,
"lat": 36.0982
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
"base": "stations",
"main": {
"temp": 275.83,
"feels_like": 271.91,
"temp_min": 275.83,
"temp_max": 275.83,
"pressure": 1030,
"humidity": 33,
"sea_level": 1030,
"grnd_level": 1026
},
"visibility": 10000,
"wind": {
"speed": 4.41,
"deg": 297,
"gust": 6.52
},
"clouds": {
"all": 0
},
"dt": 1669948994,
"sys": {
"country": "KR",
"sunrise": 1669932936,
"sunset": 1669968513
},
"timezone": 32400,
"id": 1832015,
"name": "Heunghae",
"cod": 200
}
위의 응답은 openweathermap api에서 응답받은 데이터이다. 여기서 우리가 사용해야할 데이터는 weather - id, main, icon 과 main - temp 이다. Application 단에서 이 부분만 받도록 가공해야한다.
데이터를 가공하는 작업을 Interceptor를 통해서 할 수 있다. Application 단으로 가기 전 데이터를 가로채서 가공한 후 필요한 데이터만 제공해주는 작업을 진행할 것이다.
val request = chain.request()
val response = chain.proceed(request)
val jsonString = response.body?.string() ?: ""
val json =Json{ignoreUnknownKeys = true}
val result = json.decodeFromString<WeatherContainerResponse>(jsonString)
ignoreUnknownKeys 를 true로 설정하여 사용하지 않는 속성은 정의할 필요가 없도록 설정해준다.
kotlinx serialization은 decodeFromString 메서드를 활용하여 객체로 변환할 수 있지만 gson이라면 TypeToken을 통해 객체화 작업을 진행해야한다.
response.newBuilder()
.message(response.message)
.body(Json.encodeToString(
WeatherResponse(
weather.id,
weather.type,
weather.icon,
main.temperature
)
).toResponseBody())
.build()
weather의 속성과 main의 속성을 결합해야하는 구조라서 WeatherResponse 라는 데이터 클래스로 만들어 body에 넣어주었다.
전체 코드
@Provides
@Singleton
@Named("Filtering")
fun provideFilteringInterceptor(): Interceptor {
return Interceptor { chain->
val request = chain.request()
val response = chain.proceed(request)
val jsonString = response.body?.string() ?: ""
val json =Json{ignoreUnknownKeys = true}
val result = json.decodeFromString<WeatherContainerResponse>(jsonString)
val weather = result.weathers.first()
val main = result.main
response.newBuilder()
.message(response.message)
.body(Json.encodeToString(
WeatherResponse(
weather.id,
weather.type,
weather.icon,
main.temperature
)
).toResponseBody())
.build()
}
}