Android 使用 Retrofit 从 RetrofitError 对象获取 JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20622707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:09:39  来源:igfitidea点击:

Getting JSON from RetrofitError object using Retrofit

androidretrofit

提问by neonDion

I am using the Retrofit library to do REST calls to a service I am using.

我正在使用 Retrofit 库对我正在使用的服务进行 REST 调用。

If I make an API call to my service and have a failure, the service returns a bit of JSON along with the standard HTTP error stuff. Using the RetrofitErrorobject included in the failure callback I am able to find the HTTP status code and several other things, however I am not able to retrieve the JSON that the service sends back.

如果我对我的服务进行 API 调用并出现故障,该服务会返回一些 JSON 以及标准的 HTTP 错误内容。使用RetrofitError失败回调中包含的对象,我可以找到 HTTP 状态代码和其他一些内容,但是我无法检索服务发回的 JSON。

For example, let's say I make a call to the API where I am trying to create a user. If the username already exists the service will return a 400 error code along with some JSON like this:

例如,假设我调用了我试图创建用户的 API。如果用户名已经存在,该服务将返回一个 400 错误代码以及一些 JSON,如下所示:

{"error":"Username already in use"}

Because a simple 400 error code isn't specific enough I really need access to the JSON that is returned.

因为一个简单的 400 错误代码不够具体,我真的需要访问返回的 JSON。

Does anyone know how I can get at this JSON data? I have tried looking at every field in the RetrofitErrorobject and can't find it anywhere. Is there something additional I need to be doing?

有谁知道我如何获得这个 JSON 数据?我尝试查看RetrofitError对象中的每个字段,但在任何地方都找不到它。我还需要做些什么吗?

回答by LukaCiko

You can use the getBodyAsmethod of the RetrofitErrorobject. It converts the response to a Java object similarly to other Retrofit conversions. First define a class that describes your JSON error response:

您可以使用对象的getBodyAs方法RetrofitError。与其他 Retrofit 转换类似,它将响应转换为 Java 对象。首先定义一个描述 JSON 错误响应的类:

class RestError {
    @SerializedName("code")
    public int code;
    @SerializedName("error")
    public String errorDetails;
}

Then use the previously mentioned method to get the object that describes the error in more detail.

然后使用前面提到的方法来获取更详细地描述错误的对象。

catch(RetrofitError error) {
    if (error.getResponse() != null) {
        RestError body = (RestError) error.getBodyAs(RestError.class);
        log(body.errorDetails);
        switch (body.code) {
            case 101:
                ...
            case 102:
                ...
        }
    }
}


Retrofit 2.0changed the way error responses are converter. You will need to get the right converter with the responseBodyConvertermethod and use it to convert the error body of the response. Barring exception handling this would be:

Retrofit 2.0改变了错误响应转换器的方式。您需要使用responseBodyConverter方法获取正确的转换器,并使用它来转换响应的错误正文。除非异常处理,否则将是:

Converter<ResponseBody, RestError> converter 
    = retrofit.responseBodyConverter(RestError.class, new Annotation[0]);
RestError errorResponse = converter.convert(response.errorBody());

回答by Cabezas

Try this code

试试这个代码

@Override
public void failure(RetrofitError error) {
    String json =  new String(((TypedByteArray)error.getResponse().getBody()).getBytes());
    Log.v("failure", json.toString());
}

with Retrofit 2.0

使用改造 2.0

@Override
public void onFailure(Call<Example> call, Throwable t) {
    String message = t.getMessage();
    Log.d("failure", message);
}

回答by JaredBanyard

Two-Liner with getBodyAsto get a JSON Object.

两行getBodyAs用于获取 JSON 对象。

JsonObject responseAsJson = (JsonObject) retrofitError.getBodyAs(JsonElement.class);

String message = responseAsJson.get("error").getAsString(); //=> "Username already in use"

Confirmed working in Retrofit 1.x. Not sure what changes are required for Retrofit 2.x.

确认在 Retrofit 1.x 中工作。不确定 Retrofit 2.x 需要哪些更改。

回答by ar-g

@LukaCiko answer not working now for me in retrofit 1.6.1. Here like I'm doing it now:

@LukaCiko 在改造 1.6.1 中回答现在对我不起作用。就像我现在正在做的一样:

    @Override
    public void failure(RetrofitError retrofitError) {
        String json =  new String(((TypedByteArray)retrofitError.getResponse().getBody()).getBytes());
        //own logic for example
        ExampleHandlerError error = new Gson().fromJson(json, ExampleHandlerError.class);
    }

回答by Amit Shekhar

Using this you can get the error body

使用这个你可以得到错误正文

  if (response != null && response.errorBody() != null) {
    JSONObject jsonObject = new JSONObject(response.errorBody().string());
    String error =  jsonObject.getString("error");
  }

回答by Timi Ajiboye

A much neater way to do this is to create a class that can do the parsing/conversion for you, one that you can call anytime, anywhere.

一种更简洁的方法是创建一个可以为您进行解析/转换的类,您可以随时随地调用该类。

public class ApiError {
    public String error = "An error occurred";

    public ApiError(Throwable error) {
        if (error instanceof HttpException) {
            String errorJsonString = null;
            try {
                errorJsonString = ((HttpException) 
                error).response().errorBody().string();
            } catch (IOException e) {
                e.printStackTrace();
            }
            JsonElement parsedString = new 
            JsonParser().parse(errorJsonString);
            this.error = parsedString.getAsJsonObject()
                                     .get("error")
                                     .getAsString();
        } else {
            this.error = error.getMessage() != null ? error.getMessage() : this.error;
        }
    }
}

You can now use this anywhere, like so

你现在可以在任何地方使用它,就像这样

ApiError error = new ApiError(error)
error.error

This is all from this blog post(which I wrote).

这一切都来自这篇博文(我写的)。

回答by voghDev

I was having the same. My problem was a longfield that was coming from server as an empty String"". Retrofit was giving NumberFormatExceptionbecause it seems like Gson doesn't convert an empty string to long(I'd suggest to make it 0L or something). So I had to change:

我有同样的。我的问题是long来自服务器的字段作为空String"". 改造是NumberFormatException因为 Gson 似乎不会将空字符串转换为long(我建议将其设为 0L 或其他内容)。所以我不得不改变:

long errorCode;

to

String errorCode;

As it was said before, I had no access to the JSON message when debugging. I finally found the error using RequestMaker page, maybe it helps someone else

正如之前所说,我在调试时无法访问 JSON 消息。我终于使用 RequestMaker 页面发现了错误,也许它对其他人有帮助

http://requestmaker.com/

http://requestmaker.com/

回答by Hugo Gresse

I compile many answer and wrote some code to achieve something nicer :

我编译了很多答案并编写了一些代码来实现更好的目标:

{
    "errors": {
        "email": [
            "Email not valid.",
            "Unable to find the user [email protected]."
        ]
    }
}

I take all item in 'email' and display them concatained with Guava Joiner:

我将“电子邮件”中的所有项目与 Guava Joiner 连接起来显示:

String json =  new String(((TypedByteArray)error.getResponse()
    .getBody()).getBytes());

Map<String, Object> map = new Gson().fromJson(
    json, new TypeToken<Map<String, Map<String, List<String>>>>() {}.getType());

try {
    List<String> errorsEmail = 
        (List<String>) ((Map)map.get("errors")).get("email");
    Toast.makeText(getApplicationContext(), Joiner.on("\n")
        .join(errorsEmail), Toast.LENGTH_SHORT).show();
} catch(Exception e){
    Log.e(Constants.TAG, e.getMessage());
}

回答by neonDion

So after a little more hunting I found the answer.

因此,经过更多的狩猎后,我找到了答案。

Here's my failure callback:

这是我的失败回调:

@Override public void failure(RetrofitError retrofitError) {
    String serverError = null;
    try {
        serverError = extractServerError(retrofitError.getResponse().getBody().in());
    } catch (Exception e) {
        Log.e("LOG_TAG", "Error converting RetrofitError server JSON", e);
    }

    if (serverError!=null) {
        Log.i(LOG_TAG, serverError);
    }

    Intent intent = new Intent(ACTION_REGISTRATION_ERROR);
    intent.putExtra("ServerError", serverError);
    LocalBroadcastManager.getInstance(FamDooApplication.CONTEXT).sendBroadcastSync(intent);
}

And here's the method that is called to extract the server error:

这是用于提取服务器错误的方法:

public static String extractServerError(java.io.InputStream is) {
    String serverError = null;
    String serverErrorDescription = null;
try {

    String s = convertStreamToString(is);

    JSONObject messageObject = new JSONObject(s);
    serverError = messageObject.optString("error");
    serverErrorDescription = messageObject.optString("error_description");
    if (serverErrorDescription!=null && !serverErrorDescription.equals("")) {
        return serverErrorDescription;
    } else {
        return serverError;
    }
    //String serverStack = messageObject.getString("stack");
} catch (Exception e) {
    Log.e("Basemodel", "Error converting RetrofitError server JSON", e);
}

return "";
}

This will extract the error information sent by the service that is encoded in the JSON.

这将提取服务发送的以 JSON 编码的错误信息。