【问题标题】:Retrofit Expected BEGIN_OBJECT but was STRING改造预期为 BEGIN_OBJECT,但为 STRING
【发布时间】:2020-06-30 02:17:46
【问题描述】:

大家好,我是从 Sqareup 改造库的新手。我使用 Laravel 框架创建了一个 Web 服务。当我给一个错误或格式错误的电话号码时,它应该给我一个正确的错误,如 json。 我正在尝试解析这个 JSON 响应:

{
    "message": "The given data was invalid.",
    "errors": {
        "mobile_number": [
            "The mobile number format is invalid.",
            "The mobile number must be 11 digits."
        ]
    }
}

这是我的模型类:

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

import java.util.List;


public class LoginResult {
    @SerializedName("mobile_number")
    private String mobileNumber;
    private String action;
    @SerializedName("message")
    private String message;
    @SerializedName("errors")
    private Errors errors;

    public String getMobileNumber() {
        return mobileNumber;
    }

    public String getAction() {
        return action;
    }


    public String getMessage() {
        return message;
    }


    public Errors getErrors() {
        return errors;
    }


    public static class Errors {
        @SerializedName("mobile_number")
        @Expose
        private List<String> mobileNumber = null;

        public List<String> getMobileNumber() {
            return mobileNumber;
        }
    }
}

...

import com.google.gson.annotations.SerializedName;

public class Login {
    @SerializedName("mobile_number")
    private String mobileNumber;

    public String getMobileNumber() {
        return mobileNumber;
    }

    public Login(String mobileNumber) {
        this.mobileNumber = mobileNumber;
    }
}

我的界面:

import ir.husoft.kasbokar.models.Login;
import ir.husoft.kasbokar.models.LoginResult;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;

public interface ApiInterface {
    @POST("api/auth/login")
    Call<LoginResult> login(@Body Login login);
}

这里是 ApiClient:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

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

public class ApiClient {
    public static final String BASE_URL = "http://127.0.0.1:8000/";
    public static Retrofit retrofit;

    public static Retrofit getApiClient() {
        if (retrofit == null) {
            Gson gson = new GsonBuilder().setLenient().create();
            retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(gson)).build();
        }

        return retrofit;
    }
}

我的成功方法:

ApiInterface api = ApiClient.getApiClient().create(ApiInterface.class);
String mobileNumber = etMobileNumber.getText().toString();
            Login login = new Login(mobileNumber);
            Call<LoginResult> verification = api.login(login);
            verification.enqueue(new Callback<LoginResult>() {
                @Override
                public void onResponse(Call<LoginResult> call, Response<LoginResult> response) {
                    if (response.isSuccessful()) {
                        Toast.makeText(LoginActivity.this, "Action is: " + response.body().getMessage(), Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(LoginActivity.this, "Error code: " + response.code(), Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onFailure(Call<LoginResult> call, Throwable throwable) {
                    Toast.makeText(LoginActivity.this, throwable.getLocalizedMessage(), Toast.LENGTH_LONG).show();
                }
            });

当我在我的成功方法上使用它时,它会抛出错误

预期为 BEGIN_OBJECT,但在第 1 行第 1 列为 STRING

这里有什么问题?

【问题讨论】:

  • 您的服务器显然没有为您的请求返回 JSON。将the logging interceptor 添加到您的 OkHttp/Retrofit 设置以进行调试构建,然后检查 Logcat 以查看服务器返回的内容。或者,使用 Charles Proxy 等工具来检查服务器返回的内容。或者,也许您可​​以通过服务器本身的一些工作找出服务器返回的内容。
  • 我正在使用邮递员来测试api。它与它完美搭配。此外,当我提供正确的手机号码时,它可以正常工作。只有当我给出错误的数字时,它才会给我错误。看来改装这部分有问题
  • 你在哪里使用 Gson?
  • @Mr.AF 我已经编辑了帖子

标签: android json gson retrofit


【解决方案1】:

尝试使用此代码注册您的数据类型,在我的情况下,GSON 无法转换它是即时数据类型,它是我的模型类中的 CreatedDate 字段。

Gson gson = new GsonBuilder().registerTypeAdapter(Instant.class, new JsonDeserializer<Instant>() {
            @Override
            public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                    throws JsonParseException {
                return Instant.parse(json.getAsString());
            }
        }).create();
        retrofitClient = new Retrofit.Builder()
                .baseUrl(Config.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(retroHttpClient)
                .build();

【讨论】:

    【解决方案2】:

    我发现了问题。我忘记为请求设置标头。 ApiInterface 必须如下所示:

    public interface ApiInterface {
        @Headers("Accept: application/json")
        @POST("api/auth/login")
        Call<LoginResult> login(@Body Login login);
    }
    

    【讨论】:

      【解决方案3】:

      您是否尝试过从LoginResult 中删除private String mobileNumber 并且mobileNumber 是一个数组或字符串列表。

      【讨论】:

      • 问题出在我的网络服务中。当我手动创建完全相同的 JSON 时,它就像一个魅力。但是当我使用网络服务时,它给了我这个错误。我很困惑,因为两个 JSON 响应是相同的。
      • Expected BEGIN_OBJECT but was STRING at line 1 column 1 表示您的模型与您的响应不匹配。这就是你的问题所在。
      • 在两个 JSON 文件中(一个是我手动创建的,另一个是 Web 服务给我的)我收到 422 响应代码。根据上面的代码,当我使用手动创建的 JSON 文件时,它会打印出错误代码“422”。但是当使用实际的 Web 服务时,它会引发异常。使用 Postman 时两种响应都可以
      • 您是否在 Postman 中添加了 user-agent 或令牌?您也可以发布两个 JSON 响应以确保它是相同的并且您没有错过任何内容。我刚刚注意到,但您的 BASE_URL = "http://127.0.0.1:8000/"; 是错误的。如果您模拟并调用 localhost ,它将是您手机的 localhost 而不是您的计算机。你应该把你的计算机IP改为。
      • 谢谢@Biscuit。我终于找到了问题所在。 IP 地址是正确的,因为我正在使用物理设备来测试应用程序。问题是我忘记设置 Accept 标头。在邮递员中,我使用此标头来接收正确的响应
      猜你喜欢
      • 1970-01-01
      • 2018-01-26
      • 2014-08-01
      • 2015-11-26
      • 2018-03-27
      • 2015-07-24
      • 2016-06-28
      • 2019-02-06
      • 1970-01-01
      相关资源
      最近更新 更多