SNM
SNM

Reputation: 6795

How to parse a JSON response with retrofit

So, I have given an API that returns this on a POST call

{
 "JHK":"One piece",
 "LKJ":"Two pieces",
 "OEN":"Three pieces"
}

And since this is a list but is not good formated from the backend I dont know how to get it from Android, this is what I have tried

WebService

@POST("get_user_codes.php")
suspend fun getUserCodesByMemberId(@Body member_id:String): CodesResponse

CodesResponse

data class CodesResponse(val data: List<Code>)
data class Code(val code_id:String,val name:String)

Repository

suspend fun getUserCodes(memberId:String):Result<CodesResponse>{
        return Result.Success(webService.getUserCodesByMemberId(memberId))
    }

But his is outping Null as the response, I really dont know how to bring those different objects that are supposed to be an array of object but instead they are all inside one object

Any idea ?

API INPUTS

member_id    as text string

Example of input:
{ "member_id": "1"}

API OUTPUTS

code_id: as a String

name: as a String

 {
     "JHK":"One piece",
     "LKJ":"Two pieces",
     "OEN":"Three pieces"
    }

EDIT

the values can be more than those 3 I posted, it depends on how many the response returns

Upvotes: 3

Views: 2382

Answers (3)

vt-dev0
vt-dev0

Reputation: 773

Are field names JHK LKJ OEN always the same? You said there can be more than 3, what will be the other name when it's more than 3?

AbdelraZek posted a great solution to this problem: https://stackoverflow.com/a/64246981/14259754

My version of it in Kotlin with Retrofit in mind:

Retrofit:

// Here we use ScalarsConverter to be able to return String as a response.
Retrofit.Builder()
.baseUrl("http://YourURL")
.addConverterFactory(ScalarsConverterFactory.create())
.build()
.create(YourInterfaceClass::class.java)


// Then you can proceed to your POST function
suspend fun getUserCodesByMemberId(@Body member_id:String): String

// I suggest using Response<String> so you can check the response code and process it if needed.

Then, wherever you need, just do the following:

val response = getUserCodesByMemberId

val json = JSONObject(response.body()!!) 
val array = mutableListOf<String>()

val keys: Iterator<String> = json.keys()
while (keys.hasNext()) {
  val key = keys.next()
  array.add(json[key].toString())
}

This way you can work with Json response that is unknown to you.

Upvotes: 2

Mohamed AbdelraZek
Mohamed AbdelraZek

Reputation: 2809

suppose you have response like that

 String json = {
                "JHK":"One piece",
                "LKJ":"Two pieces",
                "OEN":"Three pieces"
}

then you can get a list of values ignoring keys like:

    ArrayList<String> arr = new ArrayList<>();
    try {

        JSONObject response = new JSONObject(json);
        Iterator keys = response.keys();

        while (keys.hasNext()) {
            // loop to get the dynamic key
            String currentKey = (String) keys.next();

            // get the value of the dynamic key
             String value = response.getJSONObject(currentKey).toString();
            arr.add(value);
        }


    } catch (Throwable t) {
        Log.e("My App", "Could not parse malformed JSON: \"" + json + "\"");
    }

Upvotes: 3

SpawN31
SpawN31

Reputation: 31

It will return null because the JSON inside has different keys("JHK", "LKJ" etc). As Retrofit uses GSON, you need to create a variable with the same name as JSON keys. You will have to use JSONObject and parse the response.

Instead of using @POST("get_user_codes.php") suspend fun getUserCodesByMemberId(@Body member_id:String): CodesResponse

use @POST("get_user_codes.php") suspend fun getUserCodesByMemberId(@Body member_id:String): JSONObject

Upvotes: 1

Related Questions