Skip to content

Commit e7e0548

Browse files
committed
ApiClient: support deserializing from InputStream instead of String to bypass 2GB Java String limit
1 parent 3c53e22 commit e7e0548

File tree

3 files changed

+58
-25
lines changed

3 files changed

+58
-25
lines changed

kubernetes/src/main/java/io/kubernetes/client/openapi/ApiClient.java

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,18 @@
3838
import java.security.cert.Certificate;
3939
import java.security.cert.CertificateException;
4040
import java.security.cert.CertificateFactory;
41-
import java.security.cert.X509Certificate;
4241
import java.text.DateFormat;
4342
import java.time.LocalDate;
4443
import java.time.OffsetDateTime;
4544
import java.time.format.DateTimeFormatter;
4645
import java.util.*;
4746
import java.util.Map.Entry;
4847
import java.util.concurrent.TimeUnit;
49-
import java.util.function.Supplier;
5048
import java.util.regex.Matcher;
5149
import java.util.regex.Pattern;
5250

5351
import io.kubernetes.client.openapi.auth.Authentication;
5452
import io.kubernetes.client.openapi.auth.HttpBasicAuth;
55-
import io.kubernetes.client.openapi.auth.HttpBearerAuth;
5653
import io.kubernetes.client.openapi.auth.ApiKeyAuth;
5754

5855
/**
@@ -886,17 +883,8 @@ public <T> T deserialize(Response response, Type returnType) throws ApiException
886883
return (T) downloadFileFromResponse(response);
887884
}
888885

889-
String respBody;
890-
try {
891-
if (response.body() != null)
892-
respBody = response.body().string();
893-
else
894-
respBody = null;
895-
} catch (IOException e) {
896-
throw new ApiException(e);
897-
}
898-
899-
if (respBody == null || "".equals(respBody)) {
886+
ResponseBody respBody = response.body();
887+
if (respBody == null) {
900888
return null;
901889
}
902890

@@ -905,17 +893,25 @@ public <T> T deserialize(Response response, Type returnType) throws ApiException
905893
// ensuring a default content type
906894
contentType = "application/json";
907895
}
908-
if (isJsonMime(contentType)) {
909-
return JSON.deserialize(respBody, returnType);
910-
} else if (returnType.equals(String.class)) {
911-
// Expecting string, return the raw response body.
912-
return (T) respBody;
913-
} else {
914-
throw new ApiException(
915-
"Content type \"" + contentType + "\" is not supported for type: " + returnType,
916-
response.code(),
917-
response.headers().toMultimap(),
918-
respBody);
896+
try {
897+
if (isJsonMime(contentType)) {
898+
return JSON.deserialize(respBody.byteStream(), returnType);
899+
} else if (returnType.equals(String.class)) {
900+
String respBodyString = respBody.string();
901+
if (respBodyString.isEmpty()) {
902+
return null;
903+
}
904+
// Expecting string, return the raw response body.
905+
return (T) respBodyString;
906+
} else {
907+
throw new ApiException(
908+
"Content type \"" + contentType + "\" is not supported for type: " + returnType,
909+
response.code(),
910+
response.headers().toMultimap(),
911+
response.body().string());
912+
}
913+
} catch (IOException e) {
914+
throw new ApiException(e);
919915
}
920916
}
921917

kubernetes/src/main/java/io/kubernetes/client/openapi/JSON.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@
2929
import okio.ByteString;
3030

3131
import java.io.IOException;
32+
import java.io.InputStream;
33+
import java.io.InputStreamReader;
3234
import java.io.StringReader;
3335
import java.lang.reflect.Type;
36+
import java.nio.charset.StandardCharsets;
3437
import java.text.DateFormat;
3538
import java.text.ParseException;
3639
import java.time.LocalDate;
@@ -809,6 +812,28 @@ public static <T> T deserialize(String body, Type returnType) {
809812
}
810813
}
811814

815+
/**
816+
* Deserialize the given JSON InputStream to a Java object.
817+
*
818+
* @param <T> Type
819+
* @param inputStream The JSON InputStream
820+
* @param returnType The type to deserialize into
821+
* @return The deserialized Java object
822+
*/
823+
@SuppressWarnings("unchecked")
824+
public static <T> T deserialize(InputStream inputStream, Type returnType) throws IOException {
825+
try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) {
826+
if (isLenientOnJson) {
827+
// see https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/stream/JsonReader.html#setLenient(boolean)
828+
JsonReader jsonReader = new JsonReader(reader);
829+
jsonReader.setLenient(true);
830+
return gson.fromJson(jsonReader, returnType);
831+
} else {
832+
return gson.fromJson(reader, returnType);
833+
}
834+
}
835+
}
836+
812837
/**
813838
* Gson TypeAdapter for Byte Array type
814839
*/

kubernetes/src/test/java/io/kubernetes/client/openapi/JSONTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414

1515
import static org.assertj.core.api.Assertions.assertThat;
1616

17+
import java.io.ByteArrayInputStream;
1718
import java.io.IOException;
19+
import java.io.InputStream;
1820
import java.io.StringReader;
21+
import java.nio.charset.StandardCharsets;
1922
import java.time.OffsetDateTime;
2023

2124
import com.google.gson.Gson;
@@ -108,4 +111,13 @@ void v1ListMetaTypeValidationDisabled() throws IOException {
108111
JsonReader jsonReader = new JsonReader(new StringReader("{\"foo\":\"bar\"}"));
109112
new V1ListMeta.CustomTypeAdapterFactory().create(gson, TypeToken.get(V1ListMeta.class)).read(jsonReader);
110113
}
114+
115+
@Test
116+
void inputStream() throws IOException {
117+
String timeStr = "\"2018-04-03T11:32:26.123Z\"";
118+
OffsetDateTime dateTime = JSON.deserialize(new ByteArrayInputStream(timeStr.getBytes(StandardCharsets.UTF_8)), OffsetDateTime.class);
119+
String serializedStr = JSON.serialize(dateTime);
120+
String expectedStr = "\"2018-04-03T11:32:26.123000Z\"";
121+
assertThat(serializedStr).isEqualTo(expectedStr);
122+
}
111123
}

0 commit comments

Comments
 (0)