swagger-api / swagger-api/swagger-codegen

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

Open
#10,881 2 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

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());
	}
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the response deserialization path through JSON.deserialize and ApiClient.deserialize, then inspect how Gson's ArrayTypeAdapter handles the byte[] field. Done means a generated Java client can deserialize a type=string, format=byte response without the reported exception, while preserving normal byte-array handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
api
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.