Skip to content

Commit cc358cf

Browse files
committed
Merge pull request #1032 from xhh/retrofit-string-resp
Retrofit template: return body string directly when failed to parse response body as JSON
2 parents bc528ef + a1e6908 commit cc358cf

File tree

5 files changed

+139
-7
lines changed

5 files changed

+139
-7
lines changed

modules/swagger-codegen/src/main/resources/retrofit/service.mustache

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,20 @@ package {{invokerPackage}};
22

33
import com.google.gson.Gson;
44
import com.google.gson.GsonBuilder;
5+
import com.google.gson.JsonParseException;
6+
7+
import java.io.ByteArrayOutputStream;
8+
import java.io.InputStream;
9+
import java.io.IOException;
10+
import java.lang.reflect.Type;
11+
512
import retrofit.RestAdapter;
13+
import retrofit.converter.ConversionException;
14+
import retrofit.converter.Converter;
615
import retrofit.converter.GsonConverter;
16+
import retrofit.mime.TypedByteArray;
17+
import retrofit.mime.TypedInput;
18+
import retrofit.mime.TypedOutput;
719

820
public class ServiceGenerator {
921
// No need to instantiate this class.
@@ -15,9 +27,63 @@ public class ServiceGenerator {
1527
.create();
1628
RestAdapter adapter = new RestAdapter.Builder()
1729
.setEndpoint("{{basePath}}")
18-
.setConverter(new GsonConverter(gson))
30+
.setConverter(new GsonConverterWrapper(gson))
1931
.build();
2032
2133
return adapter.create(serviceClass);
2234
}
2335
}
36+
37+
/**
38+
* This wrapper is to take care of this case:
39+
* when the deserialization fails due to JsonParseException and the
40+
* expected type is String, then just return the body string.
41+
*/
42+
class GsonConverterWrapper implements Converter {
43+
private GsonConverter converter;
44+
45+
public GsonConverterWrapper(Gson gson) {
46+
converter = new GsonConverter(gson);
47+
}
48+
49+
@Override public Object fromBody(TypedInput body, Type type) throws ConversionException {
50+
byte[] bodyBytes = readInBytes(body);
51+
TypedByteArray newBody = new TypedByteArray(body.mimeType(), bodyBytes);
52+
try {
53+
return converter.fromBody(newBody, type);
54+
} catch (ConversionException e) {
55+
if (e.getCause() instanceof JsonParseException && type.equals(String.class)) {
56+
return new String(bodyBytes);
57+
} else {
58+
throw e;
59+
}
60+
}
61+
}
62+
63+
@Override public TypedOutput toBody(Object object) {
64+
return converter.toBody(object);
65+
}
66+
67+
private byte[] readInBytes(TypedInput body) throws ConversionException {
68+
InputStream in = null;
69+
try {
70+
in = body.in();
71+
ByteArrayOutputStream os = new ByteArrayOutputStream();
72+
byte[] buffer = new byte[0xFFFF];
73+
for (int len; (len = in.read(buffer)) != -1;)
74+
os.write(buffer, 0, len);
75+
os.flush();
76+
return os.toByteArray();
77+
} catch (IOException e) {
78+
throw new ConversionException(e);
79+
} finally {
80+
if (in != null) {
81+
try {
82+
in.close();
83+
} catch (IOException ignored) {
84+
}
85+
}
86+
}
87+
88+
}
89+
}

samples/client/petstore/retrofit/src/main/java/io/swagger/client/ServiceGenerator.java

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,20 @@
22

33
import com.google.gson.Gson;
44
import com.google.gson.GsonBuilder;
5+
import com.google.gson.JsonParseException;
6+
7+
import java.io.ByteArrayOutputStream;
8+
import java.io.InputStream;
9+
import java.io.IOException;
10+
import java.lang.reflect.Type;
11+
512
import retrofit.RestAdapter;
13+
import retrofit.converter.ConversionException;
14+
import retrofit.converter.Converter;
615
import retrofit.converter.GsonConverter;
16+
import retrofit.mime.TypedByteArray;
17+
import retrofit.mime.TypedInput;
18+
import retrofit.mime.TypedOutput;
719

820
public class ServiceGenerator {
921
// No need to instantiate this class.
@@ -15,9 +27,63 @@ public static <S> S createService(Class<S> serviceClass) {
1527
.create();
1628
RestAdapter adapter = new RestAdapter.Builder()
1729
.setEndpoint("http://petstore.swagger.io/v2")
18-
.setConverter(new GsonConverter(gson))
30+
.setConverter(new GsonConverterWrapper(gson))
1931
.build();
2032

2133
return adapter.create(serviceClass);
2234
}
2335
}
36+
37+
/**
38+
* This wrapper is to take care of this case:
39+
* when the deserialization fails due to JsonParseException and the
40+
* expected type is String, then just return the body string.
41+
*/
42+
class GsonConverterWrapper implements Converter {
43+
private GsonConverter converter;
44+
45+
public GsonConverterWrapper(Gson gson) {
46+
converter = new GsonConverter(gson);
47+
}
48+
49+
@Override public Object fromBody(TypedInput body, Type type) throws ConversionException {
50+
byte[] bodyBytes = readInBytes(body);
51+
TypedByteArray newBody = new TypedByteArray(body.mimeType(), bodyBytes);
52+
try {
53+
return converter.fromBody(newBody, type);
54+
} catch (ConversionException e) {
55+
if (e.getCause() instanceof JsonParseException && type.equals(String.class)) {
56+
return new String(bodyBytes);
57+
} else {
58+
throw e;
59+
}
60+
}
61+
}
62+
63+
@Override public TypedOutput toBody(Object object) {
64+
return converter.toBody(object);
65+
}
66+
67+
private byte[] readInBytes(TypedInput body) throws ConversionException {
68+
InputStream in = null;
69+
try {
70+
in = body.in();
71+
ByteArrayOutputStream os = new ByteArrayOutputStream();
72+
byte[] buffer = new byte[0xFFFF];
73+
for (int len; (len = in.read(buffer)) != -1;)
74+
os.write(buffer, 0, len);
75+
os.flush();
76+
return os.toByteArray();
77+
} catch (IOException e) {
78+
throw new ConversionException(e);
79+
} finally {
80+
if (in != null) {
81+
try {
82+
in.close();
83+
} catch (IOException ignored) {
84+
}
85+
}
86+
}
87+
88+
}
89+
}

samples/client/petstore/retrofit/src/main/java/io/swagger/client/api/PetApi.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,14 @@ Void updatePetWithForm(
8989
/**
9090
* Deletes a pet
9191
*
92-
* @param apiKey
9392
* @param petId Pet id to delete
93+
* @param apiKey
9494
* @return Void
9595
*/
9696

9797
@DELETE("/pet/{petId}")
9898
Void deletePet(
99-
@Header("api_key") String apiKey,@Path("petId") Long petId
99+
@Path("petId") Long petId,@Header("api_key") String apiKey
100100
);
101101

102102
/**

samples/client/petstore/retrofit/src/main/java/io/swagger/client/model/Pet.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ public class Pet {
3434
**/
3535
@ApiModelProperty(required = true, value = "")
3636
@SerializedName("photoUrls")
37-
private List<String> photoUrls = new ArrayList<String>() ;
37+
private List<String> photoUrls = null;
3838

3939
/**
4040
**/
4141
@ApiModelProperty(value = "")
4242
@SerializedName("tags")
43-
private List<Tag> tags = new ArrayList<Tag>() ;
43+
private List<Tag> tags = null;
4444
public enum StatusEnum {
4545
available, pending, sold,
4646
};

samples/client/petstore/retrofit/src/test/java/io/swagger/petstore/test/PetApiTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public void testDeletePet() throws Exception {
120120
api.addPet(pet);
121121

122122
Pet fetched = api.getPetById(pet.getId());
123-
api.deletePet(null, fetched.getId());
123+
api.deletePet(fetched.getId(), null);
124124

125125
try {
126126
fetched = api.getPetById(fetched.getId());

0 commit comments

Comments
 (0)