i want to use json file from the api-request to google sheets. from request i am getting such file:
{ "range": "'Пн'!A1:AB986", "majorDimension": "ROWS", "values": [ [ "Точка", "Отдать", "Забрать" ], [ "Заводы" ], [ "Пластик", "", "карт" ], [ "Балашов", "тов" ], [ "ПЭК", "", "док" ], [ "балашов" ], [ "таможня" ], [], [], [ "", "", "", "", " " ], [], [], [], [], [ "Центр" ], [ "ведомости", "тов1", "рем" ], [ "балашов" ], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [ "Московский" ], [ "таможня", "рем доки" ], [], [], [], [], [], [], [], [], [], [], [], [], [ "Прочее" ] ] }
(maybe it is more visible in this picture).
but for work i need only "values". for every array in "values" i want it to convert into Array of UserDataModel.
here is my code: UserDataModel.kt
data class UserDataModel(var point:String?, var get: String?, var take: String?, var isSelected: Boolean = false)
ActivityChoosing.kt (a fragment with function where i am making request)
private fun getDataFromAPI(){
var url: String = "https://sheets.googleapis.com/v4/spreadsheets/10-yIy1ZuPSjqgmXd7kO9sHobuVlpZHQnz5dMrou0cVs/values/Пн?alt=json&key=${API}"
val request = okhttp3.Request.Builder().url(url).build()
val client = OkHttpClient()
.newBuilder()
.addInterceptor { chain ->
val originalRequest = chain.request()
val builder = originalRequest
.newBuilder()
val newRequest = builder.build()
chain.proceed(newRequest)
}.build()
client.newCall(request).enqueue(object : Callback{
override fun onFailure(call: Call, e: IOException) {
Log.d("Mylog", "failed")
e.printStackTrace()
}
override fun onResponse(call: Call, response: okhttp3.Response) {
DATA_FROM_SHEETS = response.body?.string()!!
var json = JSONObject(DATA_FROM_SHEETS)
val gson = Gson()
val model_list = gson.fromJson(json["values"].toString() , Array<UserDataModel>::class.java)
Log.d("Mylog", model_list.toString() )
}
})
}
but when initializing model_list (string 4 in onResponse()) i am gettin "Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3 path $[0]". how can i do it correctly?
The serialization just doesn't work because you have an array, e.g. [ "Пластик", "", "карт" ]
that doesn't serialize to the object UserDataModel
because this is not array!
I'd approach this with an intermediate object to read easily from the JSON stream, and I wouldn't mix using JSONObject()
and Gson
.
import com.google.gson.Gson
data class UserDataModel(
val point: String?,
val get: String?,
val take: String?,
var isSelected: Boolean = false
)
data class ReaderModel(val values: List<List<String>>)
fun main(args: Array<String>) {
val source = """
{ "range": "'Пн'!A1:AB986", "majorDimension": "ROWS", "values": [ [ "Точка", "Отдать", "Забрать" ], [ "Заводы" ], [ "Пластик", "", "карт" ], [ "Балашов", "тов" ], [ "ПЭК", "", "док" ], [ "балашов" ], [ "таможня" ], [], [], [ "", "", "", "", " " ], [], [], [], [], [ "Центр" ], [ "ведомости", "тов1", "рем" ], [ "балашов" ], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [ "Московский" ], [ "таможня", "рем доки" ], [], [], [], [], [], [], [], [], [], [], [], [], [ "Прочее" ] ] }
""".trimIndent()
// first read the JSON into this object which has a List of List of Strings
// if you don't need the range and majorDimension fields, Gson will by default ignore them
val parsed = Gson().fromJson(source, ReaderModel::class.java)
println(parsed)
// now using Kotlin transform that into the desired object
val models : List<UserDataModel> = parsed.values
.drop(1) // if the first row contains titles, this is how to ignore that first row
.map {
UserDataModel(
point = if (it.size >= 1) it[0] else null,
get = if (it.size >= 2) it[1] else null,
take = if (it.size >= 3) it[2] else null,
)
}
.filter { !it.point.isNullOrBlank() } // if you want it ignore the emtpy/blank nodes
models.forEach { println(it) }
}