简体   繁体   中英

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

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 + "\"");
    }

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM