Skip to content

[JAVA] Gson exception when deserializing type=string format=byte to byte[] #10881

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
martijnvanderwoud opened this issue Jan 28, 2021 · 2 comments

Comments

@martijnvanderwoud
Copy link

Description

When processing a JSON response body containing a field with base64-encoded data (type=string, format=byte), the Gson deserializer throws an the following exception:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 13 path $.content] with root cause

java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 13 path $.content
	at com.google.gson.stream.JsonReader.beginArray(JsonReader.java:351)
	at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:70)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131)
	at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222)
	at com.google.gson.Gson.fromJson(Gson.java:932)
	at com.google.gson.Gson.fromJson(Gson.java:897)
	at com.google.gson.Gson.fromJson(Gson.java:846)
	at nl.pompkracht.portal.port.adapter.out.rest.ats.swagger.JSON.deserialize(JSON.java:134)
	at nl.pompkracht.portal.port.adapter.out.rest.ats.swagger.ApiClient.deserialize(ApiClient.java:710)
	at nl.pompkracht.portal.port.adapter.out.rest.ats.swagger.ApiClient.handleResponse(ApiClient.java:913)
	at nl.pompkracht.portal.port.adapter.out.rest.ats.swagger.ApiClient.execute(ApiClient.java:840)
...
Swagger-codegen version

3.0.23

Swagger declaration file content or url

The following schema (part of the declaration file) corresponds to the object that cannot be deserialized. More, specifically, content is the offending field here:

{
	"BinaryContentDTO": {
		"required"  : [
			"content",
			"mediaType",
			"suggestedFileName"
		],
		"type"      : "object",
		"properties": {
			"content"          : {
				"type"  : "string",
				"format": "byte"
			},
			"suggestedFileName": {
				"type": "string"
			},
			"mediaType"        : {
				"type": "string"
			}
		}
	}
}
Command line used for generation
<plugin>
	<groupId>io.swagger.codegen.v3</groupId>
	<artifactId>swagger-codegen-maven-plugin</artifactId>
	<version>3.0.23</version>
	<executions>
		<execution>
			<id>swagger-ats-java</id>
			<goals>
				<goal>generate</goal>
			</goals>
			<configuration>
				<inputSpec>../swagger-docs/ats-api-docs.json</inputSpec>
				<language>java</language>
				<invokerPackage>nl.pompkracht.portal.port.adapter.out.rest.ats.swagger</invokerPackage>
				<apiPackage>nl.pompkracht.portal.port.adapter.out.rest.ats.swagger.api</apiPackage>
				<modelPackage>nl.pompkracht.portal.port.adapter.out.rest.ats.swagger.model</modelPackage>
				<output>target/generated-sources/swagger-ats</output>
				<ignoreFileOverride>/dev/null</ignoreFileOverride>
				<generateApiTests>false</generateApiTests>
				<generateModelTests>false</generateModelTests>
				<configOptions>
					<dateLibrary>java8</dateLibrary>
				</configOptions>
			</configuration>
		</execution>
	</executions>
</plugin>
Steps to reproduce
  • Generate Java client from OpenAPI spec with an operation that contains base-64 encoded data in the response body
  • Call the relevant method in the generated code
  • Verify that the Gson exception occurs
Related issues/PRs

Found an issue with serializing byte[] array types from generated server code, but this applies to consuming base64 data from generated client code, so not really related I think

Suggest a fix/enhancement

Was able to work around the issue by adding a JsonDeserializer type adapter for byte arrays to gson, like this:

ApiClient apiClient = new ApiClient();
var serializer = apiClient.getJSON();
serializer.setGson(serializer.getGson().newBuilder()
		.registerTypeAdapter(byte[].class, new ByteArrayDeserializer())
		.create()
);

....

private static class ByteArrayDeserializer implements JsonDeserializer<byte[]> {
	@Override
	public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
		return Base64.getDecoder().decode(json.getAsString());
	}
}
@jesperronn
Copy link

jesperronn commented Jan 5, 2022

This seems related to #4824. Is this the same error?

@martijnvanderwoud could you add the label "Client: Java" so that the bug is properly categorized and findable?

@martijnvanderwoud
Copy link
Author

@jesperronn #4824 seems related indeed. However I do not think this is the same error, since that issue is fixed in v2.4.0 and this error was encountered in v3.0.23

I would like to add the label as you requested but I cannot find how to do that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants