java.lang.IllegalStateException:应为 BEGIN_OBJECT 但为 STRING

Posted

技术标签:

【中文标题】java.lang.IllegalStateException:应为 BEGIN_OBJECT 但为 STRING【英文标题】:java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING 【发布时间】:2016-06-01 20:57:49 【问题描述】:

我编写了一个Login 功能并与web service 进行通信 我正在使用Retrofit,但总是得到“失败”

获取:

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

LoginAPI.java:

public interface LoginApi 
    @FormUrlEncoded
    @POST("/retrofit_user/login.php")
    public void getlogin(
        @Field("username") String username,
        @Field("password") String password,
        Callback<User> response);

LoginActivity.java:

restAdapter = new RestAdapter.Builder().setEndpoint(ROOT_LOGIN).build();
restAdapter.setLogLevel(RestAdapter.LogLevel.FULL);
loginApi = restAdapter.create(LoginApi.class);

buttonlogin.setOnClickListener(new View.OnClickListener() 
@Override
public void onClick(View v) 

  loginApi.getlogin(editTextUsername.getText().toString(),
  editTextPassword.getText().toString(), new Callback<User>() 

  @Override
  public void success(User s, Response response) 
     Toast.makeText(LoginActivity.this,"Logged In",Toast.LENGTH_LONG).show();

    if(s != null) 
       Log.d("name:", s.getName());
       Log.d("email:", s.getEmail());
       Log.d("id:", String.valueOf(s.getId()));
    

  

  @Override
  public void failure(RetrofitError error) 

       Log.d("error:", error.toString());
 Toast.makeText(LoginActivity.this,"Failed",Toast.LENGTH_LONG).show();
          
      );
    
);

User.java:

public class User 

    String name;
    String username;
    String password;
    String email;
    int id;

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getUsername() 
        return username;
    

    public void setUsername(String username) 
        this.username = username;
    

    public String getPassword() 
        return password;
    

    public void setPassword(String password) 
        this.password = password;
    

    public String getEmail() 
        return email;
    

    public void setEmail(String email) 
        this.email = email;
    

    public int getId() 
        return id;
    

    public void setId(int id) 
        this.id = id;
    

日志说

D/Retrofit: <--- HTTP 200 http://domain.info/retrofit_user/login.php (942ms)
D/Retrofit: : HTTP/1.1 200 OK
D/Retrofit: Connection: Keep-Alive
D/Retrofit: Content-Type: text/html; charset=UTF-8
D/Retrofit: Date: Sat, 20 Feb 2016 06:00:39 GMT
D/Retrofit: Keep-Alive: timeout=5, max=100
D/Retrofit: Server: Apache/2.4.16 (Unix) OpenSSL/1.0.1e-fips mod_bwlimited/1.4
D/Retrofit: Transfer-Encoding: chunked
D/Retrofit: X-android-Received-Millis: 1455948038590
D/Retrofit: X-Android-Response-Source: NETWORK 200
D/Retrofit: X-Android-Selected-Transport: http/1.1
D/Retrofit: X-Android-Sent-Millis: 1455948037988
D/Retrofit: X-Powered-By: PHP/5.6.14
D/Retrofit: Done
D/Retrofit: <--- END HTTP (4-byte body)
D/error:: retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $
D/GraphicBuffer: create handle(0x55bb2e98) (w:256, h:66, f:1)
D/GraphicBuffer: close handle(0x55bb2e98) (w:256 h:66 f:1)

这是我的login.php 脚本:

<?php

    $objConnect = mysql_connect("localhost","username","password");
    $objDB = mysql_select_db("database");

    /*** for sample */
    // $_POST["username"] = "sun";
    // $_POST["password"] = "live";

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

    $strSQL = "select * from test_users where username = '".$username."' and  password = '".$password."' ";

    $objQuery = mysql_query($strSQL);
    $intNumRows = mysql_num_rows($objQuery);

    if($intNumRows==0)
    
    echo "Not Done" ;
    
    else
    
    echo "Done" ;
    

    mysql_close($objConnect);
?>

【问题讨论】:

您的请求正在返回 HTTP/1.1 200 OK。 200 代码用于成功请求。我认为改造没有任何问题 是的,但我的问题是为什么我登录失败 failure 方法中记录error 变量。它说什么? @KNeerajLal 刚刚检查得到:D/error:: retrofit.RetrofitError: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 预期 BEGIN_OBJECT 但在第 1 列第 1 行路径 $ 我认为你的接口方法不正确。如果我是你,我会这样写 Callback getlogin(@Field("username") String username, @Field("password") String password)。 【参考方案1】:

问题是,retrofit 需要一个 JSON 输出,它可以适合 login.phpUser 类,但所有 login.php 给出的是“未完成”或“完成”。

你必须让你的php脚本输出json格式如下,


    "name": "name",
    "username": "username",
    "password": "password",
    "email": "email",
    "id": id

您必须编辑 php 代码。会是这样的,

<?php
    $objConnect = mysql_connect("localhost","username","password");
    $objDB = mysql_select_db("database");

    /*** for sample */
    // $_POST["username"] = "sun";
    // $_POST["password"] = "live";

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

    $strSQL = "select * from test_users where username = '".$username."' and  password = '".$password."' ";

    $objQuery = mysql_query($strSQL);
    $intNumRows = mysql_num_rows($objQuery);
    if($intNumRows==0)
    
        $response["success"] = 0;
        $response["name"] = "";
        $response["username"] = "";
        $response["password"] = "";
        $response["email"] = "";
        $response["id"] = 0;
    
    else
    
        $row = mysql_fetch_array($objQuery);
        $response["success"] = 1;
        $response["name"] = $row["name"];
        $response["username"] = $row["username"];
        $response["password"] = $row["password"];
        $response["email"] = $row["email"];
        $response["id"] = $row["id"];
    

    mysql_close($objConnect);

    echo json_encode($response, JSON_NUMERIC_CHECK);
?>

还将int success; 字段添加到User 类并使用它来验证输出。所以你的成功方法是,

@Override
public void success(User s, Response response) 
    if(s != null && s.getSuccess() == 1) 
        Toast.makeText(LoginActivity.this,"Logged In",Toast.LENGTH_LONG).show();
        Log.d("name:", s.getName());
        Log.d("email:", s.getEmail());
        Log.d("id:", String.valueOf(s.getId()));
     else 
        Toast.makeText(LoginActivity.this,"Invalid!",Toast.LENGTH_LONG).show();
    


更新

id 字段是数据库中的int,但它以字符串形式返回 id。请参阅this 线程。在 php 中将 JSON_NUMERIC_CHECK 添加到 json_encode() 会有所帮助。

【讨论】:

我试过了,它可以工作,但是在 " " 双引号中获取 id,这是我的 php 的输出: "success":1,"name":"Sun Live","username" :"sun","password":"live","email":"sun@live.ifno","id":"1" 整数字段中没有 bro id 字段:id Primary int(11)

以上是关于java.lang.IllegalStateException:应为 BEGIN_OBJECT 但为 STRING的主要内容,如果未能解决你的问题,请参考以下文章