如何从 Retrofit2 获得字符串响应?

Posted

技术标签:

【中文标题】如何从 Retrofit2 获得字符串响应?【英文标题】:How to get string response from Retrofit2? 【发布时间】:2016-07-31 03:44:25 【问题描述】:

我正在做 android,正在寻找一种方法来做一个超级基本的 http GET/POST 请求。我不断收到错误消息:

java.lang.IllegalArgumentException: Unable to create converter for class java.lang.String

网络服务:

public interface WebService 
    @GET("/projects")
    Call<String> jquery();

然后在我的java中:

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://jquery.org")
       // .addConverterFactory(GsonConverterFactory.create())
        .build();

    WebService service = retrofit.create(WebService.class);
    Call<String> signin = service.jquery();

    Toast.makeText(this, signin.toString(), Toast.LENGTH_LONG).show();

我实际上只是尝试使用 GET 请求查询 jquery.org/projects 并返回它响应的字符串。怎么了?

如果我尝试实现自定义转换器(我在网上找到了一些示例),它会抱怨我没有实现抽象方法 convert(F),而这些示例都没有。

谢谢。

【问题讨论】:

【参考方案1】:

将 Retrofit2 和 ScalarsConverterFactory 添加到您的 Retrofit.Builder。

adapterBuilder = new Retrofit.Builder()
               .addConverterFactory(ScalarsConverterFactory.create())
               .addConverterFactory(GsonConverterFactory.create());

要使用 ScalarsCoverter,请将以下依赖项添加到您的构建 graddle

implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' 
implementation 'com.squareup.retrofit2:retrofit:2.9.0' //Adding Retrofit2

For API Call use: 
    Call <String> *****

安卓代码:

.enqueue(new Callback<String>() 
    @Override
    public void onResponse(Call<String> call, Response<String> response) 
        Log.i("Response", response.body().toString());
        //Toast.makeText()
        if (response.isSuccessful())
            if (response.body() != null)
                Log.i("onSuccess", response.body().toString());
            else
                Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
            
        

【讨论】:

优秀的答案...添加单行 .addConverterFactory(ScalarsConverterFactory.create()) 解决了我的问题.... 很好,它适用于 response.body().toString()。但是如果 response.errorBody().toString() 不起作用,请帮助我 adapterBuilder = new Retrofit.Builder() .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create());这段代码对我有用。我有 2 个调用接口(第一个 JSON,第二个字符串) compile 已过时,已替换为 implementation。两个库的最新版本都是 2.9.0 依赖项应该如下: implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0' //Adding Retrofit2 【参考方案2】:

我查看了 Retrofit 库,发现它根据 Call&lt;T&gt; 中的类型类解析响应。所以你有两个选择: 第一种:根据服务器的响应创建一个类。

第二个:获取响应并自己处理(不推荐Retrofit已经处理它。那么为什么要使用Retrofit,因为它是为这项工作量身定制的)。无论如何,而不是Call&lt;String&gt; 使用Call&lt;ResponseBody&gt;Call&lt;ResponseBody&gt; signin = service.jquery(); 在此之后放置以下

call.enqueue(new Callback<ResponseBody>() 
  @Override
  public void onResponse(Response<ResponseBody> response, Retrofit retrofit) 
    // handle success
   String result = response.body().string();

  

  @Override
  public void onFailure(Throwable t) 
    // handle failure
  
);

【讨论】:

什么是贡献者?它找不到它。 我编辑了它是 ResponseBody 其他变化是 body().string() 使用 ResponseBody 代替 String 有效。谢谢@ugur【参考方案3】:

要以字符串形式获取响应,您必须编写一个转换器并在初始化Retrofit时传递它。

这里是步骤。

初始化改造。

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API_URL_BASE)
                .addConverterFactory(new ToStringConverterFactory())
                .build();
        return retrofit.create(serviceClass);

用于将Retrofit's ResponseBody 转换为String 的转换器类

public class ToStringConverterFactory extends Converter.Factory 
    private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain");


    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) 
        if (String.class.equals(type)) 
            return new Converter<ResponseBody, String>() 
                @Override
                public String convert(ResponseBody value) throws IOException
                
                    return value.string();
                
            ;
        
        return null;
    

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
                                                          Annotation[] methodAnnotations, Retrofit retrofit) 

        if (String.class.equals(type)) 
            return new Converter<String, RequestBody>() 
                @Override
                public RequestBody convert(String value) throws IOException 
                    return RequestBody.create(MEDIA_TYPE, value);
                
            ;
        
        return null;
    

并且在执行service.jquery(); 之后,signin 将包含 JSON 响应。

【讨论】:

【参考方案4】:

您可以尝试以下方法:

build.gradle 文件:

dependencies 
    ...
    compile 'com.squareup.retrofit2:retrofit:2.0.1'
    ...

WebAPIService:

@GET("/api/values")
Call<String> getValues();

活动文件:

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(API_URL_BASE)                    
                .build();

        WebAPIService service = retrofit.create(WebAPIService.class);

        Call<String> stringCall = service.getValues();
        stringCall.enqueue(new Callback<String>() 
            @Override
            public void onResponse(Call<String> call, Response<String> response) 
                Log.i(LOG_TAG, response.body());
            

            @Override
            public void onFailure(Call<String> call, Throwable t) 
                Log.e(LOG_TAG, t.getMessage());
            
        );

我已经使用我的 Web 服务 (ASP.Net WebAPI) 进行了测试:

public class ValuesController : ApiController

        public string Get()
        
            return "value1";
        

Android Logcat 输出:04-11 15:17:05.316 23097-23097/com.example.multipartretrofit I/AsyncRetrofit2: value1

希望对你有帮助!

【讨论】:

【参考方案5】:
    call.enqueue(new Callback<Object>() 
        @Override
        public void onResponse(@NonNull Call<Object> call, @NonNull Response<Object> response) 
            if (response.isSuccessful()) 
                Gson gson = new Gson();
                String successResponse = gson.toJson(response.body());
                Log.d(LOG_TAG, "successResponse: " + successResponse);
             else 
                try 
                    if (null != response.errorBody()) 
                        String errorResponse = response.errorBody().string();
                        Log.d(LOG_TAG, "errorResponse: " + errorResponse);
                    
                 catch (Exception e) 
                    e.printStackTrace();
                
            
        

        @Override
        public void onFailure(@NonNull Call<Object> call, @NonNull Throwable t) 
        
    );

【讨论】:

【参考方案6】:

只需在 intercepror 中使用日志级别BODY

        OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()....
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        clientBuilder.addNetworkInterceptor(httpLoggingInterceptor);

你可以在 logcat 中看到 body,如下所示:

        D/OkHttp: "blablabla":1,.... 
        D/OkHttp: <-- END HTTP (1756-byte body)

此解决方案仅用于调试,不适用于直接在代码中获取字符串。

【讨论】:

【参考方案7】:

我更改了响应类型,而不是像这样添加 ScalarsConverterFactory

interface YourApiService 
@GET("/endpoint")
    fun getResponse(): Call<ResponseBody>

然后就可以通过

获取字符串对象了

val str = response.body().toString()

【讨论】:

【参考方案8】:

认为现在回答可能为时已晚,只需使用response.body()?.string(),您的回复就会以字符串形式出现。

【讨论】:

【参考方案9】:
String body = new String(((TypedByteArray) response.getBody()).getBytes());

如果你找到了

java.lang.ClassCastException: retrofit.client.UrlConnectionClient$TypedInputStream cannot be cast to retrofit.mime.TypedByteArray

然后把它放在你的 RestAdapter 中

.setLogLevel(RestAdapter.LogLevel.FULL)

例如:

RestAdapter restAdapter = new RestAdapter.Builder()
            .setLogLevel(RestAdapter.LogLevel.FULL)
            .setEndpoint(Root_url)
            .build();

【讨论】:

以上是关于如何从 Retrofit2 获得字符串响应?的主要内容,如果未能解决你的问题,请参考以下文章

使用 RxJava2 和 Retrofit2 时如何访问响应头?

从 retrofit2 响应中获取 JSONObject

Retrofit2:如何在具有不同字段名称的对象中接收 JSON 响应?

如何在对象 Gson/Retrofit2 中获取字符串

改造 2:从响应正文中获取 JSON

如何在不使用 GSON 或 android 中的任何其他库的情况下使用改造以字符串形式获得响应 [重复]