API string returning no value - android

I'm trying to fetch an API in kotlin with volley, but once I try to get the string from the object, I get nothing returned: W/System.err: org.json.JSONException: No value for burned
This is the API:
"requested_information": [
{
"level": 1,
"character": "一",
"kana": "いち",
"meaning": "one",
"user_specific": {
"srs": "burned",
"srs_numeric": 9,
"unlocked_date": 1464639834,
"available_date": 0,
"burned": true,
try {
val jsonArray = response.getJSONArray("requested_information")
for (i in 0 until jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(i)
// Append character to textView here
val cha = jsonObject.getString("character")
val burn = jsonObject.getString("user_specific")
val burn2: Boolean = jsonObject.getBoolean("burned")

Related

Using Kotlin to parse nested json array/object

I've read a few posts on here saying to use gson or something else.
Android Kotlin parsing nested JSON
I am planning on switching to gson later but wondering how to parse with kotlin.
JSON object:
{
"childScoresList": [
{
"child_id": "1",
"score_date": "2022-03-27",
"category_id": "1",
"category_name": "Preschool Math",
"classes": [
{
"category_name": "Preschool Math",
"class_name": "Number Blocks",
"class_id": "1",
"class_description": "Ones, Tens, Hundreds Blocks used to create given numbers.",
"skills": [
{
"skill_id": "1",
"skill_name": "Place Value",
"skill_description": "Knowing the place value of specific elements.",
"skill_score": "50"
}
]
}
]
}
]
}
Kotlin code:
val obj = JSONObject(response.toString())
val jsonArray = obj.getJSONArray("childScoresList")
for (i in 0 until jsonArray.length()) {
val categoryName = jsonArray.getJSONObject(i).getString("category_name")
}
How do I get data in class_name?
I tried various things but could not get it to work.
You must first get JSONArray from the object according to the following code and then access the class_name variable
val obj = JSONObject(js)
val jsonArray = obj.getJSONArray("childScoresList")
for (i in 0 until jsonArray.length()) {
val classes = jsonArray.getJSONObject(i).getJSONArray("classes")
for (x in 0 until classes.length()) {
val categoryName = classes.getJSONObject(x).getString("category_name")
val className = classes.getJSONObject(x).getString("class_name")
}
}

How parse array of arrays JSON with Retrofit?

When I use retrofit, I get JsonSyntaxException : Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 3 path $[0] How can I parse it?
[
[
{
"resturan_name": "هتل شاه عباس",
"menu_name": "کباب سلطانی",
"food_name": "پیش غذا"
},
{
"resturan_name": "هتل شاه عباس",
"menu_name": "کباب سلطانی",
"food_name": "پیش غذا"
}
],
[
{
"resturan_name": "هتل شاه عباس",
"menu_name": "کباب سلطانی",
"food_name": "عصرانه"
},
{
"resturan_name": "هتل شاه عباس",
"menu_name": "کباب سلطانی",
"food_name": "عصرانه"
}
]
]
You have an array of array of objects. So, when you're parsing your JSON, you have to use JSONArray:
val jsonArray = JSONArray(your_json)
The json received has a list but you maybe use json object pars in rerofit
see this link for resolve
Parse JSON array response using Retrofit & Gson
Change
Call<...> getListOf....(...);
To
Call<List<...>> getListOf....(...);
Using Response Model
Make your Response Model Class like this Using Gson,
class ResponseModel : ArrayList<ResponseModel.ResponseModelSubList>(){
class ResponseModelSubList : ArrayList<ResponseModelSubList.ResponseModelSubListItem>(){
#Parcelize
data class ResponseModelSubListItem(
#SerializedName("food_name")
val foodName: String? = "",
#SerializedName("menu_name")
val menuName: String? = "",
#SerializedName("resturan_name")
val resturanName: String? = ""
) : Parcelable
}
}
Parse JSON like this,
val response = ResponseModel() // Here response is getting from retofit or other networking lib. you use.
for (i in 0 until response.size) {
val responseList = response[i]
for (j in 0 until responseList.size) {
var foodName = responseList[j].foodName
var menuName = responseList[j].menuName
var restaurantName = responseList[j].resturanName
}
}
Using Manually Parsing
val jsonArray = JSONArray(response)
for (i in 0 until jsonArray.length()){
val jsonArray1 = jsonArray.get(i) as JSONArray
for (j in 0 until jsonArray1.length()){
var jsonObj = jsonArray1.get(j) as JSONObject
var foodName = jsonObj.getString("food_name")
var menuName = jsonObj.getString("menu_name")
var restaurantName = jsonObj.getString("resturan_name")
}
}

how to handle two different Retrofit response in Kotlin?

I have tried to read this similar thread in java in here
so I try the accepted answer there but it doesn't work. here is my problem
I will get two different JSON Response from an endpoint. if I successfully get the Restaurant data, the JSON will be like this
{
"R": {
"has_menu_status": {
"delivery": -1,
"takeaway": -1
},
"res_id": 18941862,
"is_grocery_store": false
},
"id": "18941862",
"name": "Pizza Maru",
"url": "https://www.zomato.com/jakarta/pizza-maru-1-thamrin?utm_source=api_basic_user&utm_medium=api&utm_campaign=v2.1",
"location": {
"address": "Grand Indonesia Mall, East Mall, Lantai 3A, Jl. M.H. Thamrin No. 1, Thamrin, Jakarta",
"locality": "Grand Indonesia Mall, Thamrin",
"city": "Jakarta",
"city_id": 74,
"latitude": "-6.1955810000",
"longitude": "106.8213770000",
"zipcode": "",
"country_id": 94,
"locality_verbose": "Grand Indonesia Mall, Thamrin, Jakarta"
},
"switch_to_order_menu": 0,
"cuisines": "Pizza",
"timings": "10 AM to 10 PM",
"average_cost_for_two": 180000,
"price_range": 3,
"currency": "IDR",
"thumb": "https://b.zmtcdn.com/data/pictures/chains/2/18941862/403aa36cb046e86a694e7989bb7cd545.jpg?fit=around%7C200%3A200&crop=200%3A200%3B%2A%2C%2A",
"has_online_delivery": 0,
"is_delivering_now": 0,
"store_type": "",
"phone_numbers": "021 3108656",
}
then If I send invalid restaurantID then I will get error JSON Response like this:
{
"code": 404,
"status": "Not Found",
"message": "Not Found"
}
here is the data class I made
data class Restaurant (
#SerializedName("id")
val id : Int = 0,
#SerializedName("name")
var name : String = "",
#SerializedName("url")
val url : String = "",
#SerializedName("location")
val location : Location = Location(),
#SerializedName("currency")
val currency : String = "",
#SerializedName("phone_numbers")
val phone_numbers : String = "",
#SerializedName("thumb")
val thumbnail : String = ""
)
for successful Response
data class Location (
#SerializedName("address")
val address : String = "",
#SerializedName("city")
val city : String = "",
#SerializedName("latitude")
val latitude : Double = 0.0,
#SerializedName("longitude")
val longitude : Double = 0.0,
#SerializedName("zipcode")
val zipcode : String = ""
)
for Error Response
data class ErrorResponse (
val code : Int,
val status : String,
val message : String
)
here is my Interface for my Retrofit. the idea is, I will cast it as Any first, then I will downcast either to Restaurant or ZomatoErrorResponse
interface RestaurantAPI {
#Headers("user-key: $USER_KEY_ZOMATO")
#GET("restaurant")
fun getRestaurantDetail(
#Query("res_id") id: Int
): Call<Any>
}
here is the error:
so I use my retrofit like this
val call = restaurantService.getRestaurantDetail(restaurantID)
call.enqueue(object: Callback<Any>{
override fun onResponse(call: Call<Any>, response: Response<Any>) {
if (response.isSuccessful) {
// this line is executed
Log.d("checkxxx","${response.body()}")
val restaurantData = response.body() as Restaurant // <-- but Error while casting Any to Restaurant in here
restaurant.postValue(restaurantData)
}
}
})
my app crash at that line. but actually I can successfully get the data, but I fail to cast it to Restaurant.
here the logcat of my response.body()
what went wrong in here ?
or maybe there is a better approach than this one
I finally can solve my problem using this code below
val call = restaurantService.getRestaurantDetail(restaurantID)
call.enqueue(object: Callback<Any>{
override fun onResponse(call: Call<Any>, response: Response<Any>) {
if (response.isSuccessful) {
val gson = Gson()
val restaurantData = gson.fromJson(gson.toJson(response.body()), Restaurant::class.java)
} else {
val errorBody = response.errorBody() ?: return
val type = object : TypeToken<ErrorResponse>() {}.type
val errorResponse: ErrorResponse? = gson.fromJson(errorBody.charStream(), type)
val errorMessage = errorResponse?.message ?: "Unknown Error"
}
}
})
don't forget to set the interface to be Any like this
interface RestaurantAPI {
#Headers("user-key: $USER_KEY_ZOMATO")
#GET("restaurant")
fun getRestaurantDetail(
#Query("res_id") id: Int
): Call<Any> // <---- set to Any like this
}
in my case, I have successful response and an error response. so I need to separate it like that.
but if you have 2 successful responses but it has different JSON then you need to perform null checking to restaurantData in my code above, if null then mapping it the other POJO.
You should use gson to convert json to an object
https://github.com/google/gson
Example
val gson = Gson();
val jsonInString = "{\"userId\":\"1\",\"userName\":\"Yasir\"}";
val user = gson.fromJson(jsonInString, User.class);

fetching value of specific key from json response

how can I store a specific value of a key from json response into a variable
{
"results": [
{
"name": ryan,
"roll_id": 64,
"class_id": 310,
"net_id": 95,
},
],
};
above is the json response :-
val gson = GsonBuilder().create()
val ListV = gson.fromJson(body, HomeClass::class.java)
after these 2 lines I'm totally clueless how to do it I've gone through Internet but It was hard for me to understand how to proceed further.
Your Json Structure will be
{
"results": [
{
"name": "Amiyo",
"roll_id": 1,
"class_id": 10,
"net_id": 91
},
{
....
}
]
}
Data class should be
data class HomeClass (
#SerializedName("results") val results : List<Results>
)
data class Results (
#SerializedName("name") val name : String,
#SerializedName("roll_id") val roll_id : Int,
#SerializedName("class_id") val class_id : Int,
#SerializedName("net_id") val net_id : Int
)
fromJson
val listData = gson.fromJson(jsonData, HomeClass::class.java)
Then
val totalSize = 0 until listData!!.size
if(totalSize.size>0)
{
for (i in totalSize)
{
//Your Code i==Position
}
}

How to map list of Json integers to object with the same number of integer variables?

I am having a Json response returned by server, I created a model to represent this response with Kotlin data class. Part of the response is list of integers, and I want to serialize it in object with the same number of variables.
I am trying to model this JSON response
{
"name": "My name",
"uname": "UserName",
"subs": [
[
8595622,
49,
30,
0,
1298408619,
3,
-1
],
[
8595636,
49,
30,
0,
1298409745,
3,
-1
]
]
}
The below code works fine in parsing
data class UserSubmission(
#field:SerializedName("uname")
val username: String? = null,
#field:SerializedName("subs")
val subs: List<List<Int?>?>? = null,
#field:SerializedName("name")
val name: String? = null
)
My problem is that I need the
subs: List<List<Int?>?>? to be subs: List<List<Submission?>?>?
Assuming Submission class is like that
class Submission {
val x1: Int = 0,
val x2: Int = 0,
val x3: Int = 0,
val x4: Int = 0,
val x5: Int = 0,
val x6: Int = 0,
val x7: Int = 0
}

Categories

Resources