swagger-api / swagger-api/swagger-codegen
[Java] Incorrect enum generation for boolean-based data types
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Description
Java code generator uses the wring jsonReader method in its read method when generating boolean-based enumerations.
Swagger-codegen version
3.0.33 and newer
Swagger declaration file content or url
Boolean1:
description: True or False indicator
type: boolean
enum:
- true
- false
The resulting Java code looks as follows:
package some.package;
import java.util.Objects;
import java.util.Arrays;
import io.swagger.v3.oas.annotations.media.Schema;
import com.google.gson.annotations.SerializedName;
import java.io.IOException;
import com.google.gson.TypeAdapter;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
/**
* True or False indicator
*/
@JsonAdapter(Boolean1.Adapter.class)
public enum Boolean1 {
TRUE(true),
FALSE(false);
private Boolean value;
Boolean1(Boolean value) {
this.value = value;
}
public Boolean getValue() {
return value;
}
@Override
public String toString() {
return String.valueOf(value);
}
public static Boolean1 fromValue(Boolean input) {
for (Boolean1 b : Boolean1.values()) {
if (b.value.equals(input)) {
return b;
}
}
return null;
}
public static class Adapter extends TypeAdapter<Boolean1> {
@Override
public void write(final JsonWriter jsonWriter, final Boolean1 enumeration) throws IOException {
jsonWriter.value(String.valueOf(enumeration.getValue()));
}
@Override
public Boolean1 read(final JsonReader jsonReader) throws IOException {
Object value = jsonReader.nextString();
return Boolean1.fromValue((Boolean)(value));
}
}
}
The malicious part is in the read method. The jsonReader tries to consume a string as next token, but the JSON contains boolean value in this case.
@Override
public Boolean1 read(final JsonReader jsonReader) throws IOException {
Object value = jsonReader.nextString();
return Boolean1.fromValue((Boolean)(value));
}
{"dateTime":"2022-06-02T12:02:00.888000","endOfList":false}
As a consequence, any boolean value gets rejected with the following error message:
java.lang.IllegalStateException: Expected a string but was BOOLEAN at line 1 column 59 path $.endOfList
Correct consumer method for boolean-based values should be:
@Override
public Boolean1 read(final JsonReader jsonReader) throws IOException {
Boolean value = jsonReader.nextBoolean();
return Boolean1.fromValue((Boolean)(value));
}
}
}
Command line used for generation
Download Java-Code from SwaggerHub, under Export > Client SDK > Java, or using Swagger Code Generator (e.g., in the command-line or as Maven plugin).
Steps to reproduce
- Create yaml specification with enum.
- Generate Java Code, or download Java Code from SwaggerHub
Related issues/PRs
Suggest a fix/enhancement
After inspecting the mustache template used to generate the enumeration, the definition seems not to consider boolean-based values (cf. /src/main/resources/Java/modelEnum.mustache).
@Override
public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{#isNumber}}BigDecimal value = new BigDecimal(jsonReader.nextDouble()){{/isNumber}}{{^isNumber}}{{#isInteger}}Integer value {{/isInteger}}{{^isInteger}}String value {{/isInteger}}= jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}nextString(){{/isInteger}}{{/isNumber}};
return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#jackson}}value{{/jackson}}{{^jackson}}String.valueOf(value){{/jackson}});
}
The suggested solution is to add a case for boolean values.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with src/main/resources/Java/modelEnum.mustache and reproduce the issue using the boolean enum specification shown in the report. Check the generated enum's Adapter.read method and verify generation and consumption of boolean values; done means the generated code accepts the boolean JSON token without the reported exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, openapi
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100