Arcaici
Arcaici

Reputation: 49

retrofit response null, wrong dataclass implementation?

I'm trying to add "response" json object to my login api using this api response, everything work beside it.

{
    "user": {
        "id": 1,
        "name": "lee",
        "lastname": "doe",
        "email": "[email protected]",
        "email_verified_at": null,
        "role_id": 3,
        "created_at": null,
        "updated_at": null
    },
    "token": "18|XlZE6z4jyibRoRhVRgGuSJyheyIsz8tyBT7Dz0R9",
    "response": {             
        "error": "false",                       //return always null on retrofit
        "message": "Accesso effettuato"         //return always null on retrofit
    }
}

Data class that i use for manage data:

Venditore.kt

data class Venditore (

    val user: User?=null,
    val token: String?=null,
    val response:ApiRresponse?=null
)


data class User (
    val id: Int?=null,
    val name: String?=null,
    val password:String?=null,
    val lastname:String?=null,
    val email: String?=null,
    val role_id:Int?=null,


    val email_verified_at: Any? = null,
    val created_at: Any? = null,
    val updated_at: Any? = null
)

data class ApiRresponse(
     val error:String?=null,
     val message:String?=null
)

if i try to login it works fine, but all the time

response.body()?.response?.message

return null

how should i fix it?

EDIT 1

It can't be null because i'm not fetching data but passing setted information, i thought too that could be back-end issue , but i already tested on Postman and all time return the right format(actually is the JSON that i posted above )

back end

class UserController extends Controller
{
    function index(Request $request)
    {

        $rules = array(
            'email' =>'required',
            'password' =>'required'
        );

        $messages = [
            'email.required'=> 'email mancante',
            'password.required'=> 'password mancante'

        ];

         


        $user = User::where('email', $request->email)->first();


        if (!$user || !Hash::check($request->password, $user->password)){
            
            $validator = Validator::make($request->all(),$rules,$messages);
            if($validator->fails()){
            
            
                $text_message = $validator->errors()->first();

                $response = [
                    'response'=>[
                    'error' => 'true',
                    'message' => $text_message
                    ]
                ];
                return response($response,400);
            }
            else
            {
                $response = [
                    'response'=>[
                    'error' => 'true',
                    'message' => 'le credenziali non sono corrette'
                    ]
                ];
                return response($response,401);
                
            }
        }

        $token = $user->createToken($request->device_name)->plainTextToken;
        $APiresponse = [
            'error' => 'false',
            'message' => 'Accesso effettuato'
        ];

        $response=['user'=> $user,
                   'token' =>$token,
                   'response' => $APiresponse
        ];

        return response($response, 201);
    }

retrofit call

fun login(){
            var email :String = txtEmailUser.text.toString()
            var password :String = txtPasswordUser.text.toString()
            var deviceName = android.os.Build.MODEL
            mServiceV = Common.apiV
            Log.d("response", deviceName)
           mServiceV.login(email,password,deviceName).enqueue(object : Callback<Venditore> {
                override fun onResponse(call: Call<Venditore>, response: Response<Venditore>) {
                    Log.d("code",response.code().toString())
                    Log.d("response",response.body().toString())
                    when(response.code()) {
                        400->{
                            Toast.makeText(
                                this@MainActivity,
                                response.body()?.response?.message,
                                Toast.LENGTH_SHORT
                            ).show()

                            return
                        }
                        401 -> {
                            Toast.makeText(
                                this@MainActivity,
                                response.body()?.response?.message,
                                Toast.LENGTH_SHORT
                            ).show()

                            return
                        }
                        201->{
                            GlobalVar.Myid = response.body()?.user?.id
                            GlobalVar.MyT = response.body()?.token
                            Toast.makeText(this@MainActivity, response.body()?.response?.message, Toast.LENGTH_SHORT).show()
                            startActivity(Intent(this@MainActivity, MagazzinoActivity::class.java))
                        }
                        else->{
                            if (!response.isSuccessful) {
                                Toast.makeText(
                                    this@MainActivity,
                                    "Qualcosa è andato storto",
                                    Toast.LENGTH_SHORT
                                ).show()
                                Log.d("heades", response.code().toString())
                                return
                            }
                        }
                    }



                }

                override fun onFailure(call: Call<Venditore>, t: Throwable) {
                  Toast.makeText(this@MainActivity, t.message!!, Toast.LENGTH_SHORT).show()
                }
            })
}

UPDATE

response.body()?.response?.message work when login is success i'm sorry i thought it wasn't

QUESTION in case of 400 or 401 code my api response is just

 "response": {
        "error": "true",
        "message": "le credenziali non sono corrette"
    }

could be this the problem, like should i still return in this format?

 {
    "user": {
        "id": null,
        "name": "null",
        "lastname": "null",
        "email": "null",
        "email_verified_at": null,
        "role_id": null,
        "created_at": null,
        "updated_at": null
    },
    "token": "null",
    "response": {             
        "error": "false",                       
        "message": "some message"     
    }
}

Upvotes: 0

Views: 952

Answers (1)

Arcaici
Arcaici

Reputation: 49

Finally solved!

Hope this will help someone beside me.

When 4xx code are called response.body() is empty instead of response.errorBody(), so all APIresponse will be there (if you set a custom 4xx code) or default server response.

After understood it i discover also that Retrofit doesn't convert errorBody() like Body() so you should convert by your self.

SOLUTION

val gson = Gson()
val type = object : TypeToken<APIresponse>() {}.type


var errorResponse: APIresponse? = gson.fromJson(response.errorBody()!!.charStream(), type)

//Retriving just message
Toast.makeText(this@MainActivity, errorResponse?.message, Toast.LENGTH_SHORT).show()

Upvotes: 1

Related Questions