I'm not sure there's enough of a use case to warrant doing this. Why do you want it?
 I made a scalar response body converter to deal with a legacy API that mixes application/json and text/plain. I'm happy to make a pull request if this is a common use case.
 I have exactly the same case described by @connorMathews. Also it will make the library "converter-scalars" more general. Thanks.
 You can use ResponseBody and call .string().

On Mon, Jan 11, 2016, 10:33 AM Connor notifications@github.com wrote:

> I made a scalar response body converter to deal with a legacy API that
> mixes application/json and text/plain. I'm happy to make a pull request if
> this is a common use case.
> 
> —
> Reply to this email directly or view it on GitHub
> https://github.com/square/retrofit/issues/1459#issuecomment-170645686.
 I have also GsonConverterFactory for application/json responses:
        Retrofit.Builder builder = new Retrofit.Builder()
                .baseUrl(sServiceUrl)
                .callFactory(getOkHttpClient())
                .addConverterFactory(ScalarsConverterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson));
And when I get a text/plain response it gets MalformedJsonException. 
 Use ResponseBody for those.
 Yep, a converter just moves the .string() call out of the calling code. In my case, I have endpoints that return integer item ids and others that return strings. I wanted to make the distinction explicitly in the service interface definition. I think type safety is a compelling reason but I understand if this isn't common enough to include in the project.
 I'm fine with the change. Feel free to make a PR, otherwise I'll get to it before 2.0 final.
 This was merged in.

Copy license header from another file. Use 2016 for the date.
 I'm thinking that this should assert that the string is exactly 1 character and throw an `IOException` for a non-1 length. And a test case for both the 0 and non-1 lengths.
 Actually I'll just make this change locally during the merge.
 :+1: 

Add converter for scalars to response body
retrofit-converters/scalars/src/main/java/retrofit2/ScalarsConverterFactory.java
retrofit-converters/scalars/src/main/java/retrofit2/ScalarResponseBodyConverters.java retrofit-converters/scalars/src/main/java/retrofit2/ScalarsConverterFactory.java
retrofit-converters/scalars/src/test/java/retrofit2/ScalarsConverterFactoryTest.java
diff --git a/retrofit-converters/scalars/src/main/java/retrofit2/ScalarResponseBodyConverters.java b/retrofit-converters/scalars/src/main/java/retrofit2/ScalarResponseBodyConverters.java
new file mode 100644
index 0000000000..5562dab554
--- /dev/null
+++ b/retrofit-converters/scalars/src/main/java/retrofit2/ScalarResponseBodyConverters.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 Square, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package retrofit2;
+
+import java.io.IOException;
+import okhttp3.ResponseBody;
+
+final class ScalarResponseBodyConverters {
+  private ScalarResponseBodyConverters() {
+  }
+
+  static final class StringResponseBodyConverter implements Converter<ResponseBody, String> {
+    static final StringResponseBodyConverter INSTANCE = new StringResponseBodyConverter();
+
+    @Override public String convert(ResponseBody value) throws IOException {
+      return value.string();
+    }
+  }
+
+  static final class BooleanResponseBodyConverter implements Converter<ResponseBody, Boolean> {
+    static final BooleanResponseBodyConverter INSTANCE = new BooleanResponseBodyConverter();
+
+    @Override public Boolean convert(ResponseBody value) throws IOException {
+      return Boolean.valueOf(value.string());
+    }
+  }
+
+  static final class ByteResponseBodyConverter implements Converter<ResponseBody, Byte> {
+    static final ByteResponseBodyConverter INSTANCE = new ByteResponseBodyConverter();
+
+    @Override public Byte convert(ResponseBody value) throws IOException {
+      return Byte.valueOf(value.string());
+    }
+  }
+
+  static final class CharacterResponseBodyConverter implements Converter<ResponseBody, Character> {
+    static final CharacterResponseBodyConverter INSTANCE = new CharacterResponseBodyConverter();
+
+    @Override public Character convert(ResponseBody value) throws IOException {
+      return value.string().charAt(0);
+    }
+  }
+
+  static final class DoubleResponseBodyConverter implements Converter<ResponseBody, Double> {
+    static final DoubleResponseBodyConverter INSTANCE = new DoubleResponseBodyConverter();
+
+    @Override public Double convert(ResponseBody value) throws IOException {
+      return Double.valueOf(value.string());
+    }
+  }
+
+  static final class FloatResponseBodyConverter implements Converter<ResponseBody, Float> {
+    static final FloatResponseBodyConverter INSTANCE = new FloatResponseBodyConverter();
+
+    @Override public Float convert(ResponseBody value) throws IOException {
+      return Float.valueOf(value.string());
+    }
+  }
+
+  static final class IntegerResponseBodyConverter implements Converter<ResponseBody, Integer> {
+    static final IntegerResponseBodyConverter INSTANCE = new IntegerResponseBodyConverter();
+
+    @Override public Integer convert(ResponseBody value) throws IOException {
+      return Integer.valueOf(value.string());
+    }
+  }
+
+  static final class LongResponseBodyConverter implements Converter<ResponseBody, Long> {
+    static final LongResponseBodyConverter INSTANCE = new LongResponseBodyConverter();
+
+    @Override public Long convert(ResponseBody value) throws IOException {
+      return Long.valueOf(value.string());
+    }
+  }
+
+  static final class ShortResponseBodyConverter implements Converter<ResponseBody, Short> {
+    static final ShortResponseBodyConverter INSTANCE = new ShortResponseBodyConverter();
+
+    @Override public Short convert(ResponseBody value) throws IOException {
+      return Short.valueOf(value.string());
+    }
+  }
+}
diff --git a/retrofit-converters/scalars/src/main/java/retrofit2/ScalarsConverterFactory.java b/retrofit-converters/scalars/src/main/java/retrofit2/ScalarsConverterFactory.java
index 5402455dab..3acc527902 100644
--- a/retrofit-converters/scalars/src/main/java/retrofit2/ScalarsConverterFactory.java
+++ b/retrofit-converters/scalars/src/main/java/retrofit2/ScalarsConverterFactory.java
@@ -18,6 +18,16 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
 import okhttp3.RequestBody;
+import okhttp3.ResponseBody;
+import retrofit2.ScalarResponseBodyConverters.BooleanResponseBodyConverter;
+import retrofit2.ScalarResponseBodyConverters.ByteResponseBodyConverter;
+import retrofit2.ScalarResponseBodyConverters.CharacterResponseBodyConverter;
+import retrofit2.ScalarResponseBodyConverters.DoubleResponseBodyConverter;
+import retrofit2.ScalarResponseBodyConverters.FloatResponseBodyConverter;
+import retrofit2.ScalarResponseBodyConverters.IntegerResponseBodyConverter;
+import retrofit2.ScalarResponseBodyConverters.LongResponseBodyConverter;
+import retrofit2.ScalarResponseBodyConverters.ShortResponseBodyConverter;
+import retrofit2.ScalarResponseBodyConverters.StringResponseBodyConverter;
 
 /**
  * A {@linkplain Converter.Factory converter} for strings and both primitives and their boxed types
@@ -55,4 +65,37 @@ public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] an
     }
     return null;
   }
+
+  @Override
+  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
+      Retrofit retrofit) {
+    if (type == String.class) {
+      return StringResponseBodyConverter.INSTANCE;
+    }
+    if (type == Boolean.class) {
+      return BooleanResponseBodyConverter.INSTANCE;
+    }
+    if (type == Byte.class) {
+      return ByteResponseBodyConverter.INSTANCE;
+    }
+    if (type == Character.class) {
+      return CharacterResponseBodyConverter.INSTANCE;
+    }
+    if (type == Double.class) {
+      return DoubleResponseBodyConverter.INSTANCE;
+    }
+    if (type == Float.class) {
+      return FloatResponseBodyConverter.INSTANCE;
+    }
+    if (type == Integer.class) {
+      return IntegerResponseBodyConverter.INSTANCE;
+    }
+    if (type == Long.class) {
+      return LongResponseBodyConverter.INSTANCE;
+    }
+    if (type == Short.class) {
+      return ShortResponseBodyConverter.INSTANCE;
+    }
+    return null;
+  }
 }

diff --git a/retrofit-converters/scalars/src/test/java/retrofit2/ScalarsConverterFactoryTest.java b/retrofit-converters/scalars/src/test/java/retrofit2/ScalarsConverterFactoryTest.java
index 0fe8b9be1f..d6b2146d7e 100644
--- a/retrofit-converters/scalars/src/test/java/retrofit2/ScalarsConverterFactoryTest.java
+++ b/retrofit-converters/scalars/src/test/java/retrofit2/ScalarsConverterFactoryTest.java
@@ -24,6 +24,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 import retrofit2.http.Body;
+import retrofit2.http.GET;
 import retrofit2.http.POST;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -50,6 +51,18 @@ interface Service {
       @POST("/") Call<ResponseBody> longObject(@Body Long body);
       @POST("/") Call<ResponseBody> shortPrimitive(@Body short body);
       @POST("/") Call<ResponseBody> shortObject(@Body Short body);
+
+      @GET("/") Call<Object> object();
+
+      @GET("/") Call<String> stringObject();
+      @GET("/") Call<Boolean> booleanObject();
+      @GET("/") Call<Byte> byteObject();
+      @GET("/") Call<Character> charObject();
+      @GET("/") Call<Double> doubleObject();
+      @GET("/") Call<Float> floatObject();
+      @GET("/") Call<Integer> integerObject();
+      @GET("/") Call<Long> longObject();
+      @GET("/") Call<Short> shortObject();
   }
 
   @Rule public final MockWebServer server = new MockWebServer();
@@ -64,7 +77,7 @@ interface Service {
     service = retrofit.create(Service.class);
   }
 
-  @Test public void unsupportedTypesNotMatched() {
+  @Test public void unsupportedRequestTypesNotMatched() {
     try {
       service.object(null);
       fail();
@@ -79,7 +92,7 @@ interface Service {
     }
   }
 
-  @Test public void supportedTypes() throws IOException, InterruptedException {
+  @Test public void supportedRequestTypes() throws IOException, InterruptedException {
     RecordedRequest request;
 
     server.enqueue(new MockResponse());
@@ -201,4 +214,56 @@ interface Service {
     assertThat(request.getHeader("Content-Length")).isEqualTo("2");
     assertThat(request.getBody().readUtf8()).isEqualTo("11");
   }
+
+  @Test public void unsupportedResponseTypesNotMatched() {
+    try {
+      service.object();
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertThat(e).hasMessage(
+          "Unable to create converter for class java.lang.Object\n"
+              + "    for method Service.object");
+      assertThat(e.getCause()).hasMessage(
+          "Could not locate ResponseBody converter for class java.lang.Object. Tried:\n"
+              + " * retrofit2.BuiltInConverters\n" + " * retrofit2.ScalarsConverterFactory");
+    }
+  }
+
+  @Test public void supportedResponseTypes() throws IOException, InterruptedException {
+    server.enqueue(new MockResponse().setBody("test"));
+    Response<String> stringResponse = service.stringObject().execute();
+    assertThat(stringResponse.body()).isEqualTo("test");
+
+    server.enqueue(new MockResponse().setBody("true"));
+    Response<Boolean> booleanResponse = service.booleanObject().execute();
+    assertThat(booleanResponse.body()).isTrue();
+
+    server.enqueue(new MockResponse().setBody("5"));
+    Response<Byte> byteResponse = service.byteObject().execute();
+    assertThat(byteResponse.body()).isEqualTo((byte) 5);
+
+    server.enqueue(new MockResponse().setBody("b"));
+    Response<Character> characterResponse = service.charObject().execute();
+    assertThat(characterResponse.body()).isEqualTo('b');
+
+    server.enqueue(new MockResponse().setBody("13.13"));
+    Response<Double> doubleResponse = service.doubleObject().execute();
+    assertThat(doubleResponse.body()).isEqualTo(13.13);
+
+    server.enqueue(new MockResponse().setBody("13.13"));
+    Response<Float> floatResponse = service.floatObject().execute();
+    assertThat(floatResponse.body()).isEqualTo(13.13f);
+
+    server.enqueue(new MockResponse().setBody("13"));
+    Response<Integer> integerResponse = service.integerObject().execute();
+    assertThat(integerResponse.body()).isEqualTo(13);
+
+    server.enqueue(new MockResponse().setBody("1347"));
+    Response<Long> longResponse = service.longObject().execute();
+    assertThat(longResponse.body()).isEqualTo(1347L);
+
+    server.enqueue(new MockResponse().setBody("134"));
+    Response<Short> shortResponse = service.shortObject().execute();
+    assertThat(shortResponse.body()).isEqualTo((short) 134);
+  }
 }
