In Kotlin it is known as JSON to Data Class, Traditionally in JAVA it is known as JSON to POJO. This class also known as Data class or Model class. This online kotlin data class generator with dark theme will generate data class with GSON mapping. This will make nice single line format for each field to maintain your code more easily. Input JSON in the box, then you will see the result in the below box in realtime.
JSON Tips: JSON key(Parameter) name should be camelCase or snack_case, Don't use same root object/array name multiple time as that will be class name. JSON string or a JSON array as top level value are not allowed. JSON First value type of an array is considered as data type.
You just can use GSON which is developed by google. GSON Link: https://github.com/google/gson
dependencies {
implementation 'com.google.code.gson:gson:2.9.0' // Gradle
// implementation("com.google.code.gson:gson:2.9.0") // Gradle KTS
}
GSON is not for only Android you can use it in your any Kotlin or JAVA project. Here is an example use of GSON:
val myJson = """
{
"user_name": "john123",
"email": "[email protected]",
"name": "John Doe"
}
""".trimIndent()
val gson = Gson()
var mUser = gson.fromJson(myJson, UserData::class.java)
println(mUser.userName)
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.7.1")
implementation("com.google.code.gson:gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.4.0") // for cache
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3")
See this file for all libraries
First file: AllApi.kt
object AllApi {
private external fun baseUrlFromJNI(boolean: Boolean): String
const val BASE_URL = "https://api.example.com/"
private const val V1 = "v1/"
const val DATA_LIST = V1 + "my_data.php"
}
Second file: ApiState.kt
sealed class ApiState {
object Loading : ApiState()
class Failure(val e: Throwable) : ApiState()
class Success(val data: Any) : ApiState()
object Empty : ApiState()
}
Third file: RetrofitClient.kt
object RetrofitClient {
private const val TIME_OUT: Long = 120
private val gson = GsonBuilder().setLenient().create()
private val okHttpClient = OkHttpClient.Builder()
.readTimeout(TIME_OUT, TimeUnit.SECONDS)
.connectTimeout(TIME_OUT, TimeUnit.SECONDS)
.addInterceptor { chain ->
val resp = chain.proceed(chain.request())
// Deal with the response code
if (resp.code() == 200) {
try {
val myJson = resp.peekBody(2048).string() // peekBody() will not close the response
println(myJson)
} catch (e: Exception) {
println("Error parse json from intercept..............")
}
} else {
println(resp)
}
resp
}.build()
val retrofit: RetrofitInterface by lazy {
Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(AllApi.BASE_URL)
.client(okHttpClient)
.build().create(RetrofitInterface::class.java)
}
}
Fourth File: RetrofitInterface.kt
interface RetrofitInterface {
@GET(AllApi.DATA_LIST)
suspend fun getDataList(): List
}
Example Repository code:
class MyDataRepository {
fun getDataList(): Flow> = flow {
val r = RetrofitClient.retrofit.getDataList()
emit(r)
}.flowOn(Dispatchers.IO)
}
class MyDataVM(private var repository: MyDataRepository) : ViewModel() {
val myDataList: MutableStateFlow = MutableStateFlow(ApiState.Empty)
fun getDataList() = viewModelScope.launch {
myDataList.value = ApiState.Loading
repository.getDataList()
.catch { e ->
myDataList.value = ApiState.Failure(e)
}.collect { data ->
myDataList.value = ApiState.Success(data)
}
}
}
Example ViewModelFactory:
class MyDataViewModelFactory(private val repository: MyDataRepository): ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
return MyDataVM(repository) as T
}
}
private lateinit var myDataVM: MyDataVM
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
myDataVM = ViewModelProvider(
this,
MyDataViewModelFactory(MyDataRepository())
)[MyDataVM::class.java]
}
myDataVM.getDataList()
lifecycleScope.launchWhenCreated {
myDataVM.myDataList.collect {
apiStateCheck(binding.indicator, it) { mData ->
val myObj = mData as List
// TODO Here is your rest of the code with myObj
}
}
}
lifecycleScope.launchWhenCreated {
myDataVM.myDataList.collect {
apiStateCheck(binding.indicator, it) { mData ->
val myObj = mData as List
// TODO Here is your rest of the code with myObj
}
}
}
This is how you can use GSON, Retrofit with MVVM pattern.
Complete source code is here: GitHub: Android-Modern-API-Call-Kotlin-MVVM
Thanks.