【问题标题】:Retrofit errorBody strange behaviour改造errorBody的奇怪行为
【发布时间】:2017-08-19 15:38:43
【问题描述】:

如果我写:

String str = response.errorBody().string();
String errors = Misc.get_errors(str);

一切正常(get_errors 是一个 final static 方法,它只能重新格式化 str)。

但是如果我直接写:

String errors = Misc.get_errors(response.errorBody().string());

失败了。

我的 Java 有点生疏了,我想知道为什么结果不一样。

编辑:

public final static String get_errors(String errors) {

        StringBuilder sb = new StringBuilder();

        try {
                JSONObject jObjError = new JSONObject(errors);

                Iterator<String> it = jObjError.keys();

                while (it.hasNext()) {

                    sb.append(jObjError.get(it.next()).toString().replace("[\"", "").replace("\"]", ""));
                    sb.append(System.getProperty("line.separator"));

                }

            } catch (Exception e) {
                e.printStackTrace();

            }



        return sb.toString();


Callback<Joueur> callback = new Callback<Joueur>(){

                                                          @Override
                                                          public void onResponse(Call<Joueur> call, Response<Joueur> response){

                                                              // display message if http error(s)
                                                              if(!response.isSuccessful()){
                                                                  try{
                                                                      String raw_errors = response.errorBody().string();
                                                                      String errors = Misc.get_errors(raw_errors);
                                                                      Toast display = Toast.makeText(getApplicationContext(), errors, Toast.LENGTH_LONG);
                                                                      display.show();
                                                                  }
                                                                  catch(Exception e){
                                                                      e.printStackTrace();
                                                                  }

                                                              }
                                                              // otherwise, launch new intent
                                                              else{

                                                                  Intent myIntent = new Intent(Inscription_activity.this, Connexion_activity.class);
                                                                  Inscription_activity.this.startActivity(myIntent);

                                                              }


                                                              }

【问题讨论】:

  • 它是如何失败的?你能附上你的堆栈跟踪吗?
  • 错误是什么?编译时间?
  • 第二种情况,String为空。
  • 你的尝试怎么样?你在读 response.errorBody() 两次吗?
  • 我已经在第一篇文章中添加了整个代码。

标签: java android json retrofit


【解决方案1】:

消费了error body后(因为是ResponseBody),会变空(因为是buffer,被消费了)。这就是为什么它只在第一次工作。

如果您想复制要使用的响应,您可以这样做。

val oldResponseBody = it.response().errorBody()
val responseBytes = oldResponseBody.bytes()
val reponseCopy1 = ResponseBody.create(oldResponseBody.contentType(), responseBytes)
val reponseCopy2 = ResponseBody.create(oldResponseBody.contentType(), responseBytes)

请注意,此方法一次将响应的所有字节复制到内存中。

【讨论】:

  • 有什么办法可以解决这个问题?我需要多个级别的响应正文!
  • 是的,我修改了答案。
  • 是的,行得通!但我需要将数据放回同一个对象中。我将 RxJava 与 Retrofit 一起使用,并处理 API 级别和 UI 级别的错误。
  • 我认为一种选择是修改 Retrofit 的 RxJava 适配器并将另一个运算符添加到它的链中,并将错误转换为 RetainableResponseBody 之类的内容,您可以在其中存储字节并且不要使其为空消费。我确实搜索过,目前ResponseBody 无法保留它的字节流。
  • 没问题,请选择它作为接受的一个(如果是!)。
【解决方案2】:

获取错误正文的只读副本(在 OkHttp3 版本4.9.1 上测试):

response()?.errorBody()?.source()?.buffer?.snapshot()?.utf8()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 2019-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多