【问题标题】:Read plain text response from server using Retrofit使用 Retrofit 从服务器读取纯文本响应
【发布时间】:2020-11-04 03:30:50
【问题描述】:

我正在开发一个使用 Retrofit 进行网络操作的应用程序。就目前而言,GsonConverterFactory 处理序列化一切正常。这是我如何设置Retrofit

Retrofit.Builder()
        .baseUrl("<base url>") 
        .client(client)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()

现在我需要连接到以text/plain; charset=utf-8 格式返回内容的旧服务。这是改造界面

@GET("https://<domain>/<endpoint>?Type=Query")
suspend fun callStatus(@Query("userId") id: Int): Response<String>

这将返回有效用户的呼叫状态。例如,如果用户有效并且有状态,它会以纯文本形式返回“活动”。如果没有有效用户,则返回错误码#1005

我可以像这样添加自定义转换器工厂(在网络上找到)

final class StringConverterFactory implements Converter.Factory {
    private StringConverterFactory() {}

    public static StringConverterFactory create() {
        return new StringConverterFactory();
    }

    @Override
    public Converter<String> get(Type type) {
        Class<?> cls = (Class<?>) type;
        if (String.class.isAssignableFrom(cls)) {
            return new StringConverter();
        }
        return null;
    }

    private static class StringConverter implements Converter<String> {
        private static final MediaType PLAIN_TEXT = MediaType.parse("text/plain; charset=UTF-8");

        @Override
        public String fromBody(ResponseBody body) throws IOException {
            return new String(body.bytes());
        }

        @Override
        public RequestBody toBody(String value) {
            return RequestBody.create(PLAIN_TEXT, convertToBytes(value));
        }

        private static byte[] convertToBytes(String string) {
            try {
                return string.getBytes("UTF-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

但我没有看到它有什么不同。此外,它还可以将 JSON 伪装成普通文本并破坏所有现有服务。有没有更好的方法来处理这种情况?我想为纯文本设置单独的改造实例,虽然有点脏。您还有其他建议/解决方案吗?

已编辑

响应头包含的内容类型为 Content-Type: text/plain; charset=utf-8

有效用户的实际响应

Active

无效用户的实际响应

#1005

【问题讨论】:

  • 嗨。您是否尝试过使用 okhttp 获取原始 html 并检查 Response.body “Active”中是否存在。还是您肯定需要改造?
  • 这对我来说很好stackoverflow.com/a/41138352/6478047。试一试

标签: android kotlin retrofit retrofit2 okhttp


【解决方案1】:

更新


您注册转换器工厂的顺序很重要。 ScalarsConverterFactory 必须先来。


应该可以在构建 Retrofit 对象时添加ScalarsConverterFactory
这可以与其他 json 转换器一起完成,例如

Retrofit.Builder()
        .baseUrl("<base url>") 
        .client(client)
        .addConverterFactory(ScalarsConverterFactory.create())
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()

之后,您应该能够收到明文响应。

您可能还需要将此添加到您的依赖项中:

implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'

【讨论】:

  • Scalars 和 Gson 不能一起工作,Retrofit 无法识别纯字符串和 json 字符串响应。
  • 这是正确的,您可能需要指定要使用哪个转换,但标量转换器工厂会做您想要的。 For example。不同之处在于这些样本使用一个转换器。您应该专注于“如何使用两者并为这个特定的遗留调用使用正确的”,甚至可能为每个使用自定义改造,因为它们本质上是不同的 API。 (见something like this
  • 它似乎没有正确选择响应。我将尝试添加一个自定义转换器,看看是否有帮助
  • “没有正确选择响应”是什么意思?你得到什么错误?
【解决方案2】:

以下是我获取纯文本响应的方式(使用 Java 而不是 Kotlin)。

第一步

在你的 gradle(模块)中;

    implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'

第二步

创建接口

public interface MyInterface {
    @GET("something.php")
    Call<String> getData(@Query("id") String id,
                         @Query("name") String name);
}

第三步

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://example.com")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();

MyInterface myInterface = retrofit.create(MyInterface.class);
Call<String> call = myInterface.getData("id","myname");
call.enqueue(new Callback<String>() {
                    @Override
                    public void onResponse(Call<String> call, Response<String> response) {
                        String plain_text_response = response.body();
                    }

                    @Override
                    public void onFailure(Call<String> call, Throwable t) {

                    }
                });

【讨论】:

    【解决方案3】:

    您不需要使用您可以使用的 Converter.Factory 的自定义实现

    // your coroutine context
        val response = callStatus(userId)
        if(response.isSuccessful){
            val plainTextContent = response.body()
            // handle plainText
        } else {
         //TODO: Handle error
        }
     //...
    

    【讨论】:

    • 我也有同样的印象,但它给了我MalformedJsonException 检查编辑的部分,看看是否响起任何铃声
    【解决方案4】:

    首先要检查两件事,即功能不应暂停,并且您的响应应在回调中

    无需添加额外的标量实现。

    @GET
        fun getJson(
            @Url baseUrl: String = slab_pro
        ): Call<DataClass>
    

    【讨论】:

      猜你喜欢
      • 2021-09-15
      • 2016-05-28
      • 2013-07-27
      • 1970-01-01
      • 2012-12-07
      • 1970-01-01
      • 1970-01-01
      • 2018-12-02
      • 1970-01-01
      相关资源
      最近更新 更多