【问题标题】:Android Retrofit - POST request doesn't work, but in Postman it worksAndroid Retrofit - POST 请求不起作用,但在 Postman 中它起作用
【发布时间】:2017-03-02 08:36:50
【问题描述】:

这是我得到的错误:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 应为 BEGIN_OBJECT,但在第 1 行第 1 列路径 $

我从 Postman 收到的 JSON 响应:

{
  "title": "test title",
  "body": "test body",
  "userId": 1,
  "id": 101
}

这就是我回应来自其他 API(使用 slim2 框架)的响应的方式:

$app->post('/posts', function() use($app){
    $res = array(
        "title" => $app->request->post('title'),
        "body" => $app->request->post('body'),
        "userId" => 1,
        "id" => 101
        );
    echoResponse(201, $res);
});

echoResponse方法:

function echoResponse($status_code, $response) {
    $app = \Slim\Slim::getInstance();
    $app->status($status_code);
    $app->contentType('application/json');

    echo json_encode($response);
}

我调用 API 的方法:

public void sendPost(String title, String body) {
    mAPIService.savePost(title, body, 1).enqueue(new Callback<Post>() {
        @Override
        public void onResponse(Call<Post> call, Response<Post> response) {
            Log.i(TAG, "post sendPost to onResponse.");
            if(response.isSuccessful()) {
                showResponse(response.body().toString());
                Log.i(TAG, "post submitted to API." + response.body().toString());
            }
        }

        @Override
        public void onFailure(Call<Post> call, Throwable t) {
            Log.e(TAG, "Unable to submit post to API.");
            Log.e(TAG, t.toString());
        }
    });
}

APIServie 接口:

public interface APIService {
@POST("/posts")
@FormUrlEncoded
Call<Post> savePost(@Field("title") String title,
                    @Field("body") String body,
                    @Field("userId") long userId);
}

我是如何获得retrofit 实例的:

mAPIService = ApiUtils.getAPIService();
public class ApiUtils {
    private ApiUtils() {}
    public static final String BASE_URL = "http://myurl/v1/";

    public static APIService getAPIService() {
        return RetrofitClient.getClient(BASE_URL).create(APIService.class);
    }

}
public class RetrofitClient {
   private static Retrofit retrofit = null;

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

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

我发布所有这些的原因是我找不到问题出在哪里,因为我从 API 获得的 JSON 响应看起来不错,我调用 API 的方式看起来不错。有很多与此相关的问题可以在这里找到。但我找不到我的问题的答案。请给我一个解决方案。谢谢

编辑: @Darpan 和 @Fred 是对的。我启用了日志记录以进行改造。就是这么写的

D/OkHttp: --> POST http://myurl/posts http/1.1
D/OkHttp: Content-Type: application/x-www-form-urlencoded
D/OkHttp: Content-Length: 26
D/OkHttp: title=vz&body=gde&userId=1
D/OkHttp: --> END POST (26-byte body)
D/OkHttp: <-- 200 OK http://mywebsite/404/
    <html of my 404 page>
D/OkHttp: <-- END HTTP (2119-byte body) 

它给了我服务器的 404.html 文件作为响应。但是当我从 POSTMAN 调用相同的 API 时,它给了我想要的结果。

所以基本上我可以从 POSTMAN 访问并获取结果,但不能使用改造从 Android 应用程序中使用它

知道如何解决吗? 可能是什么问题?

【问题讨论】:

  • 我不是 php 大师,但从改造/gson 错误看来,您的整个 json 响应都被编码为一个完整的字符串。你能仔细检查一下吗?
  • @Fred 我查过了。在响应标头中显示“Content-Type →application/json”。所以我认为这没有问题。我可能是错的,我不知道其他方法可以做到这一点。我是 PHP 新手,而且很苗条
  • 我怀疑您分享的响应是您在改造时得到的响应。您能否启用日志记录以进行改造,并查看您的 API 调用得到什么响应?它必须是一个字符串,即您的响应引发了一些错误,因此不是以“{” 开头
  • @Darpan 感谢您的日志改造想法。这样可行。你是对的。请检查帖子中的编辑
  • 从基本 url 中删除 v/ 并将其放入 @POST("v/posts/"):请参阅此答案 stackoverflow.com/questions/42430403/…

标签: android retrofit retrofit2 slim postman


【解决方案1】:

从您的基本网址 http://myurl/v1/ 中删除最后一个 /

这就是它抛出 404 的原因。

【讨论】:

    【解决方案2】:

    创建波纹管类并将Call&lt;Post&gt;更改为Call&lt;MyResponse&gt;

    public class MyResponse {
    
        @SerializedName("result")
        private String result;
    
        @SerializedName("data")
        private Data data;
    
        public class Data {
    
            @SerializedName("title")
            @Expose
            private String title;
    
            @SerializedName("body")
            @Expose
            private String body;
    
            @SerializedName("userId")
            @Expose
            private String userId;
    
            @SerializedName("id")
            @Expose
            private String id;
    
            public String getTitle() {
                return title;
            }
    
            public void setTitle(String title) {
                this.title = title;
            }
    
            public String getBody() {
                return body;
            }
    
            public void setBody(String body) {
                this.body = body;
            }
    
            public String getUserId() {
                return userId;
            }
    
            public void setUserId(String userId) {
                this.userId = userId;
            }
    
            public String getId() {
                return id;
            }
    
            public void setId(String id) {
                this.id = id;
            }
        }
    
        public String getResult() {
            return result;
        }
    
        public void setResult(String result) {
            this.result = result;
        }
    
        public Data getData() {
            return data;
        }
    
        public void setData(Data data) {
            this.data = data;
        }
    }
    

    你应该像这样改变你的 json 格式

    {
        "result" : "success",
        "data" : {
                "title":"title",
                "body":"body",
                "user_id":"userid",
                "id":"id"
        }   
    }
    

    现在您可以像这样 MyResponse res= response.body();

    来访问它

    并且还像这样打印响应 Log.d("response", new Gson().toJson(res));

    【讨论】:

    • 我有一个类似于这个的名为 Post 的课程。我发现问题出在哪里。检查编辑。感谢您的回答。
    • @SumitBahatt 还没有。我可以使用 POSTMAN 的 API,它工作正常。但不能使用改造从 Android 应用程序中使用它。可能是什么问题?
    • 我已将其放在正在编辑的帖子中。你能检查一下吗
    • 该错误表示您是访问对象,但实际上它是字符串,这就是我告诉您检查您的响应的原因
    • 我在服务器中的 404.html 文件作为响应
    【解决方案3】:

    我遇到了同样的错误,我的根本原因是我的 Api 期待与 https://my.url.com 的调用,而 Android 正在使用 http://my.url.com 进行请求。我们查看了日志,服务器将请求视为 GET 而不是 POST。

    将网址更改为https:// 后,它工作正常。希望这对其他人有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-05
      • 2023-04-06
      • 1970-01-01
      • 2019-12-05
      • 2018-07-26
      • 1970-01-01
      • 2021-12-24
      相关资源
      最近更新 更多