Błąd podczas pobierania danych z RESPONSE ( Retrofit )

0

Cześć ! Mam problem ! Otóż niedawno zacząłem uczyć się używać biblioteki Retrofit ( dotychczas używałem Volley ). Mój JSON jest poprawny ( sprawdzałem go )
Wyskakuje mi taki błąd:

E/MainActivity: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $

JSON:

{
    "statusOfLogin": 1, 
    "id": "2"
}

MainActivity:

public void onClick(View view)
    {
        EditText usernameET = findViewById(R.id.usernameET);
        EditText passwordET = findViewById(R.id.passwordET);

        String username = usernameET.getText().toString();
        String password = passwordET.getText().toString();

        final RequestModel requestModel = new RequestModel();

        requestModel.setUsername(username);
        requestModel.setPassword(password);

        Gson gson = new GsonBuilder()
                .setLenient()
                .create();

        final Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();

        WebAPIInterface webAPIInterface = retrofit.create(WebAPIInterface.class);

        webAPIInterface.login(requestModel).enqueue(new Callback<ResponseModel>() {
            @Override
            public void onResponse(Call<ResponseModel> call, Response<ResponseModel> response) {

                if(response.isSuccessful())
                {
                    Log.v(TAG, "Response is successful !!!");
                    Gson gson = new GsonBuilder()
                            .setLenient()
                            .create();

                    gson.fromJson(response.toString(), ResponseModel.class);
                }
                else
                {
                    Log.v(TAG, "Response isn't successful !!!");
                }

            }

            @Override
            public void onFailure(Call<ResponseModel> call, Throwable t) {
                Log.e(TAG, t.toString());
            }
        });
    }

ResponseModel:

public class ResponseModel {

    @SerializedName("statusOfLogin")
    @Expose
    private Integer statusOfLogin;
    @SerializedName("id")
    @Expose
    private Integer id;
    // gettery i settery

RequestModel:

public class RequestModel
{
    @SerializedName("username")
    private String username;

    @SerializedName("password")
    private String password;

WebAPIInterface:

public interface WebAPIInterface
{
    @POST("retrofitLogin.php")
    Call<ResponseModel> login(@Body RequestModel requestModel);
}

Kod PHP po stronie serwera:

<?php
require "connect.php";

$response = array();


$username = $_POST["username"];
$password = $_POST["password"];


$mysql_qry = "SELECT `Haslo` FROM `dane_logowania` WHERE `Login` = '$username'";
$result = mysqli_query($conn ,$mysql_qry);


$data = $result->fetch_array();
if(password_verify($password, $data['Haslo']))
{
     $qry = "SELECT `ID` FROM `dane_logowania` WHERE `Login` = '$username'";
     $res = mysqli_query($conn, $qry);
     $data1 = $res->fetch_array();
     
     $response["statusOfLogin"] = 1;
     $response["id"] = $data1["ID"];
     
     echo json_encode($response);

}
else
{
   $response["statusOfLogin"] = 0;
   $response["id"] = 0;
   
   echo json_encode($response);
}
?>

Jak to naprawić ?
I jeszcze jedno pytanie.
Czy ten POST jest dobrze wykonany ( w sensie czy do skryptu są przekazane dane z klasy RequestModel )?

0

A rozumiesz co chcesz zrobić tymi linijkami kodu?

@Override
public void onResponse(Call<ResponseModel> call, Response<ResponseModel> response) {
  if(response.isSuccessful())
  {
    Gson gson = new GsonBuilder()
        .setLenient()
        .create();
 
    gson.fromJson(response.toString(), ResponseModel.class);
  }
}

Podpowiedź - zobacz jak wygląda response.toString().

0

Odnośnie pytania w komentarzach - Retrofit zwraca Ci już zdeserializowany obiekt. Po to instaluje się w nim konwerter dla Gsona, żebyś nie musiał sam dbać o mapowanie z JSONa na obiekty i z obiektów na JSONy. Żeby pobrać swój obiekt musisz wywołać response.body().

Poczytaj o tym, czym są typy generyczne, przejrzyj przykłady na Githubie Retrofita. Poza tym Retrofit jest jedną z najpopularnieszych bibliotek, więc powinieneś sam umieć znaleźć takie informacje w Internecie.

0

Jak pobieram dane używając response.body() to pokazuje mi się NullPointerException.
A w sprawie tego gson-a. Czyli muszę mieć w klasach @SerializedName() jako adnotacje czy nie ( oczywiście tylko jak używam retrofit-a )?

0

No to nie masz poprawnej odpowiedzi z serwera. Co do @SerializedName, to nie jest to konieczne, jeżeli zmienna nazywa się tak samo jak pole w JSONie i nie obfuskujesz kodu z tymi polami.

0

To jaka ma być odpowiedź z serwera. Odpowiedź powinna być poprawna. JSON jest poprawny

0

W zasadzie ta którą wkleiłeś, jest poprawna. W każdym razie jest zrozumiała dla Gsona, żeby przekonwertować ją do Twojego obiektu.

{
    "statusOfLogin": 1, 
    "id": "2"
}

Masz problem z szukaniem przyczyn problemów, a co z tym idzie z informowaniem innych, żeby mogli Ci pomóc. Jakby ktoś Ciebie poprosił, żebyś mu wyjaśnił, gdzie ma błąd i powiedział Ci, że leci NullPointerException, to jak byś zareagował? Musisz się nauczyć precyzyjnie wyrażać, jeżeli chcesz być programistą (choć to nie tyczy się tylko tego zawodu).

Wklej kawałek kodu, który powoduje błąd i wrzucaj pełen komunikat a nie tylko jego wyrywek czy typ wyjątku.

0

Ok, dzięki za poradę. Wiem że popełniał jeszcze dużo błędów. Jak by ludzie na tym forum poznali mój prawdziwy wiek to pewnie nie brali by mnie na poważnie.
A kod wkleję jak do domu wrócę

0

Popróbowałem ze zmianą kodu i już mniej więcej wiem z czym nie działa.
Skrypt PHP teraz wygląda tak:

<?php
require "connect.php";


if($_SERVER['REQUEST_METHOD'] === 'POST')
{
   $jsonToDecode = file_get_contents('php://input');
   $json = json_decode($jsonToDecode, true);

   $username = $obj['username'];
   $password = $obj['password'];

   $mysql_qry = "SELECT `Haslo` FROM `dane_logowania` WHERE `Login` = '$username'";
   $result = mysqli_query($conn ,$mysql_qry);


   $data = $result->fetch_array();
   if(password_verify($password, $data['Haslo']))
   {
      $qry = "SELECT `ID` FROM `dane_logowania` WHERE `Login` = '$username'";
      $res = mysqli_query($conn, $qry);
      $data1 = $res->fetch_array();
     
      $resp = array("statusOfLogin" => 1, "id" => $data1["ID"]);
     
      echo json_encode($resp);

   }
   else
   {
      $resp = array("statusOfLogin" => 0, "id" => 0);
   
      echo json_encode($resp);
   }
}
else
{
   $response['statusOfLogin'] = 9999;
   $response['id'] = 0;
}


?>

W skrypcie PHP gdy ustawiam zamiast

$username = $obj['username'];
$password = $obj['password'];

to:

$username = "adfgh"; // to samo wysyłam jako login i hasło do skryptu
$password = "adfgh";

to wtedy w LogCat pokazuje mi się odpowiednie** ID** i odpowiedni STATUS.( takie jakie jest ustawione w bazie MySQL. response.body.toString daje

V/MainActivity: Response is successful !!!
    RESPONSE: retrofit2.Response@c4b6a77

Kiedy w kodzie jest to pierwsze ( z** $obj** ) to wtedy wyrzuca mi błąd ( tylko jedną linijkę ) :

E/MainActivity: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
0

Już rozwiązałem mój problem. W interfejsie zamiast @Body użyłem @Field.

1 użytkowników online, w tym zalogowanych: 0, gości: 1