使用 Retrofit 从服务器读取纯文本响应

Ren*_*ith 4 android kotlin retrofit okhttp retrofit2

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

Retrofit.Builder()
        .baseUrl("<base url>") 
        .client(client)
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()
Run Code Online (Sandbox Code Playgroud)

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

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

这将为有效用户返回呼叫状态。例如,如果用户有效并且有状态,它会以纯文本形式返回“Active”。如果没有有效用户,则返回错误代码#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);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

已编辑

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

有效用户的实际响应

Active
Run Code Online (Sandbox Code Playgroud)

无效用户的实际响应

#1005
Run Code Online (Sandbox Code Playgroud)

Adr*_*n K 9

更新


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


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

Retrofit.Builder()
        .baseUrl("<base url>") 
        .client(client)
        .addConverterFactory(ScalarsConverterFactory.create())
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()
Run Code Online (Sandbox Code Playgroud)

之后,您应该能够接收纯文本响应。

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

implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
Run Code Online (Sandbox Code Playgroud)


ZBo*_*ala 6

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

步骤1

在你的 gradle(模块)中;

    implementation 'com.squareup.retrofit2:converter-scalars:2.9.0'
Run Code Online (Sandbox Code Playgroud)

第二步

创建一个接口

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

第三步

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) {

                    }
                });
Run Code Online (Sandbox Code Playgroud)


Arp*_*kar 0

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

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