Android Studio中根据NIK自动获取数据库姓名的代码报错求助
问题描述
我是Android Studio新手,需要实现填写NIK字段后点击按钮,自动从数据库获取对应姓名的功能。目前编写Java代码时遇到问题,点击按钮出现错误:
java.lang.illegalStateException : Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $
以下是相关信息:
数据库结构
| NIK | NAMA |
|---|---|
| 96296 | Farrasta |
| 94878 | Alfian |
应用视图

相关代码
按钮点击事件代码
btnGet.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { NikKry = etNik.getText().toString(); getNama(); } }); private void getNama(){ APIRequestData armNama = RetroMaster.konekRetrofit().create(APIRequestData.class); Call<DataMaster> tampilNama = armNama.ardGetNama(NikKry); tampilNama.enqueue(new Callback<DataMaster>() { @Override public void onResponse(Call<DataMaster> call, Response<DataMaster> response) { if (response.isSuccessful()){ etNama.setText(response.body().getNAMA()); } } @Override public void onFailure(Call<DataMaster> call, Throwable t) { Toast.makeText(TambahActivity.this, "Gagal "+t.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
DataMaster实体类代码
package com.example.crudoracle.Model; public class DataMaster { private String NIK; private String NAMA; public String getNIK() { return NIK; } public void setNIK(String NIK) { this.NIK = NIK; } public String getNAMA() { return NAMA; } public void setNAMA(String NAMA) { this.NAMA = NAMA; } }
API请求代码
@FormUrlEncoded @POST("getnama.php") Call<DataMaster> ardGetNama( @Field("NIK") String NIK );
PHP接口代码
<?php include ("koneksi.php"); $NIK = $_POST['NIK']; $query = "SELECT NAMA FROM MASTER_KRY WHERE NIK = '$NIK'"; $eksekusi = oci_parse($conn, $query); $cek = oci_execute($eksekusi); $response = array(); while($ambil = oci_fetch_object($eksekusi)){ $F["NAMA"] = $ambil->NAMA; array_push($response, $F); } echo json_encode($response); oci_close($conn); ?>
Postman响应结果
[{"NAMA":"Alfian U"}]
问题原因及解决方法
原因分析
错误提示的核心是:Retrofit期望解析单个JSON对象,但服务器返回的是JSON数组。从Postman响应可见,接口返回的是[{"NAMA":"Alfian U"}],是包含单个对象的数组;而Android代码用Call<DataMaster>接收,期望的是单个DataMaster对象,类型不匹配导致报错。
解决方法
两种方案任选其一即可:
方案一:修改Android端代码适配数组响应
- 修改API请求接口:将返回类型改为
Call<List<DataMaster>>
@FormUrlEncoded @POST("getnama.php") Call<List<DataMaster>> ardGetNama( @Field("NIK") String NIK );
- 更新
getNama()方法的回调逻辑:
private void getNama(){ APIRequestData armNama = RetroMaster.konekRetrofit().create(APIRequestData.class); Call<List<DataMaster>> tampilNama = armNama.ardGetNama(NikKry); tampilNama.enqueue(new Callback<List<DataMaster>>() { @Override public void onResponse(Call<List<DataMaster>> call, Response<List<DataMaster>> response) { if (response.isSuccessful() && !response.body().isEmpty()){ // 取数组第一个元素的姓名值 etNama.setText(response.body().get(0).getNAMA()); } else { Toast.makeText(TambahActivity.this, "未找到对应NIK的姓名", Toast.LENGTH_SHORT).show(); } } @Override public void onFailure(Call<List<DataMaster>> call, Throwable t) { Toast.makeText(TambahActivity.this, "请求失败:"+t.getMessage(), Toast.LENGTH_SHORT).show(); } }); }
方案二:修改PHP代码返回单个对象
因为业务上一个NIK对应唯一姓名,可直接返回单个对象而非数组:
<?php include ("koneksi.php"); $NIK = $_POST['NIK']; $query = "SELECT NAMA FROM MASTER_KRY WHERE NIK = '$NIK'"; $eksekusi = oci_parse($conn, $query); $cek = oci_execute($eksekusi); // 只获取第一条结果 $ambil = oci_fetch_object($eksekusi); $response = array(); if($ambil){ $response["NAMA"] = $ambil->NAMA; } echo json_encode($response); oci_close($conn); ?>
修改后接口返回{"NAMA":"Alfian U"},Android端现有代码无需修改即可正常解析。
额外建议
你的PHP代码存在SQL注入风险,建议使用绑定变量的方式优化SQL执行:
$query = "SELECT NAMA FROM MASTER_KRY WHERE NIK = :nik"; $eksekusi = oci_parse($conn, $query); oci_bind_by_name($eksekusi, ':nik', $NIK); $cek = oci_execute($eksekusi);
内容的提问来源于stack exchange,提问作者Farrasta K S
相关产品推荐
相关产品推荐

