Reputation: 27
I want my android app to read data from Google Sheets. I have tried that and got below as Response:
{
"items": [
{
"Company": "Tata",
"Car": "Nexon",
"Model": "XZ",
"Price": 1400000,
"Range": 320,
"BatterySize": 30
},
{
"Company": "Tata",
"Car": "Nexon",
"Model": "XZ+",
"Price": 1500000,
"Range": 320,
"BatterySize": 30
}
]
}
The first thing that I want to do is get value using Key like "Company" or other.
I also want to filter and only display all items where the price is less than 1500000.
Here is what I am doing to get data from the URL
val url = URL("My_URL")
val client = OkHttpClient()
val request = okhttp3.Request.Builder()
.url(url)
.get()
.build()
val response = client.newCall(request).execute()
val responseBody = response.body!!.string()
val jsonArray = JSONObject(responseBody)
val name = jsonArray.getString("items")
println(name)
It prints:
[
{
"Company": "Tata",
"Car": "Nexon",
"Model": "XZ",
"Price": 1400000,
"Range": 320,
"BatterySize": 30
},
{
"Company": "Tata",
"Car": "Nexon",
"Model": "XZ+",
"Price": 1500000,
"Range": 320,
"BatterySize": 30
}
]
Which is not List but Sting I guess. Not able to understand what to do with this String.
Let me know if you need more information.
Upvotes: 1
Views: 2035
Reputation: 11608
You might want to try kotlinx.serialization which is a part of the Kotlin language. To use it in your Android project (Groovy syntax, if you use Kotlin DSL in your Gradle files it will be slightly different):
Add this to your top-level build.gradle: classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
In your module-level build.gradle, add apply plugin: 'kotlinx-serialization'
OR if you're using newer syntax, add kotlinx-serialization
to your plugins {}
block
To (de)serialize your data, consider adding the following helper extensions (note: this example uses the default Json
; see below to get an idea of how to configure you own instance):
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
inline fun <reified T> T.toJson(): String = Json.encodeToString(this)
inline fun <reified T> String.fromJson(): T = Json.decodeFromString(this)
WARNING: using the default Json
, you will get into trouble if the data actually provided by your API does not match your declared format, so you may want to configure a Json instance to use in your (de)serializer (and also assign default values to your data fields):
val json = Json {
ignoreUnknownKeys = true
coerceInputValues = true
// more config if needed
}
This article provides a good explanation of that config.
Q: When do I need to configure Json myself?
A: If you are sure that your API will always return the data you expect, you are good to go with the default one. In all other cases it would be wise to use a custom config.
Based on you example, a single item from your list would look like that:
@Serializable
data class Item(
@SerialName("Company") val company: String,
@SerialName("Car") val car: String,
@SerialName("Model") val model: String,
@SerialName("Price") val price: Float,
@SerialName("Range") val range: Int,
@SerialName("BatterySize") val batterySize: Int
)
You also need a "holder" for your parsed items:
@Serializable
data class Items(@SerialName("items") val data: List<Item>)
Here's how you can get your data:
val url = URL("My_URL")
val client = OkHttpClient()
val request = okhttp3.Request.Builder()
.url(url)
.get()
.build()
val response = client.newCall(request).execute()
val items = response.body!!.string().fromJson<Items>().data
I also want to filter and only display all items where the price is less than 1500000.
Sure, you can now apply any List operation to your data:
items.filter { it.price < 1500000 }.forEach { item ->
println("item $item passed the price filter")
}
A couple of things to note:
!!
) in production code, always you the safe call (?
) operatorUpvotes: 3