【问题标题】:(Retrofit / Android) Parsing java object into PHP Rest API(Retrofit / Android) 将 java 对象解析为 PHP Rest API
【发布时间】:2018-12-30 01:03:27
【问题描述】:

我尝试使用改造将数据从 android 发送到我的 MySQL 数据库,但是从 android 发送的数据不会解析为 php 支持的对象,因此它不会输入到数据库中。原来api说所有参数都丢失了。所以我假设android将不受支持的java对象发送到我的rest api中。这是我的代码:

改造addBooking方法:

private void addBooking(HashMap<String, String> booking){
        Call<HashMap<String, String>> call = userService.addBooking(booking);
        call.enqueue(new Callback<HashMap<String, String>>() {
            @Override
            public void onResponse(Call<HashMap<String, String>> call, Response<HashMap<String, String>> response) {
                Log.i("RESPONSE", response.toString());
                if(response.isSuccessful()){
                    //Toast.makeText(FormRuanganActivity.this, "Success!", Toast.LENGTH_SHORT).show();
                    Log.i("API RESPONSE", response.body().toString());
                    Snackbar.make(scrollViewForm, "Data successfully inputted", Snackbar.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<HashMap<String, String>> call, Throwable t) {
                Log.e("ERROR: ", t.getMessage());
                Toast.makeText(FormRuanganActivity.this, "ERROR: " + t.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }

这是我的 php api 代码:

case 'createBooking':
                isParametersAvailable(array('title', 'start', 'end', 'nama', 'alamat', 'nohp', 'image', 'dosen',
                    'ruang', 'organisasi', 'alasan', 'mulai', 'selesai'));

                $db = new dboperation();

                $result = $db->createBooking(
                    $_POST['title'],
                    $_POST['start'],
                    $_POST['end'],
                    $_POST['nama'],
                    $_POST['alamat'],
                    $_POST['nohp'],
                    $_POST['image'],
                    $_POST['dosen'],
                    $_POST['ruang'],
                    $_POST['organisasi'],
                    $_POST['alasan'],
                    $_POST['mulai'],
                    $_POST['selesai']);

                if($result){
                    $response['error'] = false;
                    $response['message'] = "Booking added!";
                    $response['bookings'] = $db->getBookings();
                }
                else{
                    $response['error'] = true;
                    $response['message'] = "Error occured!";
                }
                break;

在使用 HashMap 之前,我尝试使用我的 Booking 对象(我从模型类创建),但它也没有将数据输入到我的数据库中。我的问题是如何解析 android 发送到 php rest api 的对象,以便 api 可以将数据输入到我的数据库中?谢谢你的帮助

这是我在日志猫中得到的回复:

07-22 17:16:09.472 12761-12761/com.telkomuniversity.iflab.spriflab I/RESPONSE: Response{protocol=http/1.1, code=200, message=OK, url=xxxx}
07-22 17:16:09.472 12761-12761/com.telkomuniversity.iflab.spriflab I/HTTP RESPONSE: {message=Parameters title,start,end,nama,alamat,nohp,image,dosen,ruang,organisasi,alasan,mulai,selesai missing, error=true}

已编辑 ==

RetrofitCLient 类:

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitClient {

    private static Retrofit retrofit = null;

    public static Retrofit getClient(String url){
        if(retrofit == null){
            retrofit = new Retrofit.Builder().baseUrl(url)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }

        return retrofit;
    }

}

用户服务接口:

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.DELETE;
import retrofit2.http.FieldMap;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;

public interface UserService {

    @GET("api.php?apicall=getBookings")
    Call<List<BookingInfo>> getBookings();

    @POST("api.php?apicall=createBooking")
    Call<HashMap<String, String>> addBooking(@Body HashMap<String, String> booking);

    @PUT("api.php?apicall=updateStatus")
    Call<BookingInfo> updateStatus(@Path("status") String status, @Body BookingInfo booking);

    @DELETE("api.php?apicall=deleteBooking&={id}")
    Call<BookingInfo> deleteBooking(@Path("id") int id);

}

以及 HashMap 的创建:

HashMap<String, String> params = new HashMap<>();
        params.put("title", nim);
        params.put("start", "10/16/2018");
        params.put("end", "10/17/2018");
        params.put("nama", name);
        params.put("alamat", alamat);
        params.put("nohp", hp);
        params.put("image", "test.jpg");
        params.put("dosen", dosen);
        params.put("ruang", ruang);
        params.put("organisasi", organisasi);
        params.put("alasan", alasan);
        params.put("mulai", waktuMulai);
        params.put("selesai", waktuSelesai);

FormRuanganActivity 类:

import android.app.DatePickerDialog;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.Toast;

import com.telkomuniversity.iflab.spriflab.ApiUtils.APIProperties;
import com.telkomuniversity.iflab.spriflab.ApiUtils.UserService;
import com.telkomuniversity.iflab.spriflab.Model.BookingInfo;
import com.telkomuniversity.iflab.spriflab.R;

import java.util.Calendar;
import java.util.HashMap;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class FormRuanganActivity extends AppCompatActivity implements View.OnClickListener{

    // item dari layout
    private EditText etNama, etNIM, etAlamat,etHP, etAlasan, etDosen, etOrganisasi;
    private EditText etDate; // not editable
    private Spinner spinnerRuangan, spinnerWaktuMulai, spinnerWaktuSelesai;
    private Button btnDate, btnSubmit;
    private ProgressBar progressBar;
    private ScrollView scrollViewForm;

    // isi spinner
    private static final String[] itemSpinnerRuangan = {"IFLAB1", "IFLAB2", "IFLAB3",
            "IFLAB4", "IFLAB5", "IKLAB1", "IKLAB2",};
    private static final String[] itemSpinnerWaktuMulai = {"--Waktu Mulai--", "18:00:00", "18:30:00", "19:00:00",
            "19:30:00", "20:00:00", "20:30:00", "21:00:00", "21:30:00", "22:00:00"};
    private static final String[] itemSpinnerWaktuSelesai = {"--Waktu Selesai--", "18:00:00", "18:30:00", "19:00:00",
            "19:30:00", "20:00:00", "20:30:00", "21:00:00", "21:30:00", "22:00:00"};

    // datepicker variabel
    private DatePickerDialog.OnDateSetListener dateListener;

    // api properties
    public static final int CODE_GET_REQUEST = 1024;
    public static final int CODE_POST_REQUEST = 1025;
    private UserService userService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_form_ruangan);

        scrollViewForm = findViewById(R.id.scrollViewForm);

        setTitle("Booking Form");

        userService = APIProperties.getUserService();

        progressBar = findViewById(R.id.progressBar);

        etNama = findViewById(R.id.etNama);
        etNIM = findViewById(R.id.etNIM);
        etAlamat = findViewById(R.id.etAlamat);
        etHP = findViewById(R.id.etHP);
        etAlasan = findViewById(R.id.etAlasan);
        etDosen = findViewById(R.id.etDosen);
        etOrganisasi = findViewById(R.id.etOrganisasi);

        etDate = findViewById(R.id.etDate);

        btnDate = findViewById(R.id.btnDate);
        btnSubmit = findViewById(R.id.btnSubmit);
        btnDate.setOnClickListener(this);
        btnSubmit.setOnClickListener(this);

        spinnerRuangan = findViewById(R.id.spinnerRuangan);
        ArrayAdapter<String> arrayAdpt =  new ArrayAdapter<String>(FormRuanganActivity.this,
                android.R.layout.simple_spinner_item, itemSpinnerRuangan);
        arrayAdpt.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerRuangan.setAdapter(arrayAdpt);
        spinnerRuangan.setSelection(0);
        spinnerRuangan.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                // on progress
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
                // on progress
            }
        });

        spinnerWaktuMulai = findViewById(R.id.spinnerWaktuMulai);
        ArrayAdapter<String> arrayAdptMulai = new ArrayAdapter<String>(FormRuanganActivity.this,
                android.R.layout.simple_spinner_item, itemSpinnerWaktuMulai);
        arrayAdptMulai.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerWaktuMulai.setAdapter(arrayAdptMulai);
        spinnerWaktuMulai.setSelection(0);
        spinnerWaktuMulai.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                //on progress
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
                //on progress
            }
        });

        spinnerWaktuSelesai = findViewById(R.id.spinnerWaktuSelesai);
        ArrayAdapter<String> arrayAdptSelesai = new ArrayAdapter<String>(FormRuanganActivity.this,
                android.R.layout.simple_spinner_item, itemSpinnerWaktuSelesai);
        arrayAdptSelesai.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spinnerWaktuSelesai.setAdapter(arrayAdptSelesai);
        spinnerWaktuSelesai.setSelection(0);
        spinnerWaktuSelesai.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
                //on progress
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {
                //on progress
            }
        });

        dateListener = new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker datePicker, int year, int month, int day) {
                try {
                    month = month + 1;
                    String date = day + "-" + month + "-" + year;

                    etDate.setText(date);
                }
                catch(Exception e){
                    Toast.makeText(FormRuanganActivity.this, "Error Occurred", Toast.LENGTH_SHORT).show();
                }
            }
        };


    }


    @Override
    public void onClick(View view) {
        if(view == btnSubmit){
            try {
                //Toast.makeText(FormRuanganActivity.this, "Under Maintenance", Toast.LENGTH_SHORT).show();
                createBooking();

            } catch(Exception e){
                e.printStackTrace();
                Toast.makeText(FormRuanganActivity.this, "Exception detected" , Toast.LENGTH_SHORT).show();
            }
        }
        else if(view == btnDate){
            try {
                Calendar cal = Calendar.getInstance();
                int year = cal.get(Calendar.YEAR);
                int month = cal.get(Calendar.MONTH);
                int day = cal.get(Calendar.DAY_OF_MONTH);

                DatePickerDialog dialog = new DatePickerDialog(FormRuanganActivity.this,
                        android.R.style.Theme_Holo_Light_Dialog_MinWidth,
                        dateListener,
                        year, month, day);
                dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
                dialog.show();
            } catch (Exception e){
                Toast.makeText(FormRuanganActivity.this, "Exception detected!", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void createBooking(){
        String name = etNama.getText().toString().trim();
        String nim = etNIM.getText().toString().trim();
        String alamat = etAlamat.getText().toString().trim();
        String hp = etHP.getText().toString().trim();
        String alasan = etAlasan.getText().toString().trim();
        String dosen = etDosen.getText().toString().trim();
        String organisasi = etOrganisasi.getText().toString().trim();

        String ruang = spinnerRuangan.getSelectedItem().toString();
        String waktuMulai = spinnerWaktuMulai.getSelectedItem().toString();
        String waktuSelesai = spinnerWaktuSelesai.getSelectedItem().toString();

        String tanggal = etDate.getText().toString().trim();

        int spn1 = spinnerWaktuMulai.getSelectedItemPosition();
        int spn2 = spinnerWaktuSelesai.getSelectedItemPosition();

        if(TextUtils.isEmpty(name)){
            etNama.setError("Silahkan masukkan nama anda.");
            etNama.requestFocus();
            return;
        }
        else if(TextUtils.isEmpty(nim)){
            etNIM.setError("Silahkan masukkan NIM anda.");
            etNIM.requestFocus();
            return;
        }
        else if(TextUtils.isEmpty(alamat)){
            etAlamat.setError("Silahkan masukkan alamat anda.");
            etAlamat.requestFocus();
            return;
        }
        else if(TextUtils.isEmpty(hp)){
            etHP.setError("Silahkan masukkan Nomor HP anda.");
            etHP.requestFocus();
            return;
        }
        else if(TextUtils.isEmpty(alasan)){
            etAlasan.setError("Silahkan masukkan alasannya.");
            etAlasan.requestFocus();
            return;
        }
        else if(TextUtils.isEmpty(dosen)){
            etDosen.setError("Silahkan masukkan nama dosen penanggung jawabnya.");
            etDosen.requestFocus();
            return;
        }
        else if(TextUtils.isEmpty(organisasi)){
            etOrganisasi.setError("Silahkan masukkan nama organisasi anda.");
            etOrganisasi.requestFocus();
            return;
        }
        else if(TextUtils.isEmpty(tanggal)){
            etDate.setError("Silahkan masukkan tanggal peminjaman.");
            etDate.requestFocus();
            return;
        }
        else if(spn1 == 0){
            Toast.makeText(FormRuanganActivity.this, "Waktu Mulai harap diisi", Toast.LENGTH_SHORT).show();
            spinnerWaktuMulai.requestFocus();
        }
        else if(spn2 == 0){
            Toast.makeText(FormRuanganActivity.this, "Waktu Selesai harap diisi", Toast.LENGTH_SHORT).show();
            spinnerWaktuSelesai.requestFocus();
        }

        // tanggal start sama end nya masih fix di tanggal ini belom dirubah jadi editable
        HashMap<String, String> params = new HashMap<>();
        params.put("title", nim);
        params.put("start", "10/16/2018");
        params.put("end", "10/17/2018");
        params.put("nama", name);
        params.put("alamat", alamat);
        params.put("nohp", hp);
        params.put("image", "test.jpg");
        params.put("dosen", dosen);
        params.put("ruang", ruang);
        params.put("organisasi", organisasi);
        params.put("alasan", alasan);
        params.put("mulai", waktuMulai);
        params.put("selesai", waktuSelesai);


        BookingInfo b = new BookingInfo();
        b.setNim(nim);
        b.setTanggalmulai("10/16/2018");
        b.setTanggalselesai("10/17/2018");
        b.setNama(name);
        b.setAlamat(alamat);
        b.setNohp(hp);
        b.setImage("image.jpg");
        b.setDosen(dosen);
        b.setRuangan(ruang);
        b.setOrganisasi(organisasi);
        b.setAlasan(alasan);
        b.setWaktumulai(waktuMulai);
        b.setWaktuselesai(waktuSelesai);

        addBooking(params);

    }


    private void addBooking(HashMap<String, String> booking){
        Call<HashMap<String, String>> call = userService.addBooking(booking);
        call.enqueue(new Callback<HashMap<String, String>>() {
            @Override
            public void onResponse(Call<HashMap<String, String>> call, Response<HashMap<String, String>> response) {
                Log.i("RESPONSE", response.toString());
                if(response.isSuccessful()){
                    //Toast.makeText(FormRuanganActivity.this, "Success!", Toast.LENGTH_SHORT).show();
                    Log.i("API RESPONSE", response.body().toString());
                    Snackbar.make(scrollViewForm, "Data successfully inputted", Snackbar.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<HashMap<String, String>> call, Throwable t) {
                Log.e("ERROR: ", t.getMessage());
                Toast.makeText(FormRuanganActivity.this, "ERROR: " + t.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

错误日志:

07-22 18:54:55.142 14250-14250/com.telkomuniversity.iflab.spriflab E/ERROR:: Expected a string but was BEGIN_ARRAY at line 1 column 55 path $.

【问题讨论】:

  • 请发布您的改造代码以及调用 addBooking(HashMap booking) 的代码并创建 Booking 的 HashMap。确保您在 isParametersAvailable(array(..)); 中的 PHP 代码中设置的键中发送值
  • @VirajPatel 我已添加代码
  • @IIehcram 尝试@FieldMap 而不是@Body 一次并检查。
  • @VirajPatel 它显示了一个异常,它说“java.lang.IllegalArgumentException: @FieldMap 参数只能与表单编码一起使用。”
  • @POST("api.php?apicall=createBooking")上方添加@FormUrlEncoded并检查

标签: php android retrofit


【解决方案1】:

@llehcram 下面的代码解决了你的问题

@FormUrlEncoded
@POST("api.php?apicall=createBooking")
Call<BookingInfo> addBooking(@FieldMap HashMap<String, String> booking);

注意:如果您在处理 BookingInfo 响应时遇到错误,那么您必须创建能够处理您的响应的 POJO/Model 类。您可以从响应 herehere 创建 POJO 类

你可以阅读更多关于@FieldMapherehere的信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 2017-01-24
    相关资源
    最近更新 更多