Fix issue with URI type in the enum (#17126)

* fix(java): fix URI inner enum for gson

* fix(java): fix URI enum for gson

* fix(java): fix URI enum for microprofile

* fix(java): fix URI import for native enum

* fix(java): add tests for URI enum
This commit is contained in:
hhomar 2023-12-13 06:19:51 +00:00 committed by GitHub
parent 4c4388e3c8
commit 28b2c75ac8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 156 additions and 15 deletions

View File

@ -177,6 +177,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
private boolean hasDiscriminatorWithNonEmptyMapping;
private boolean isAnyType;
private boolean isUuid;
private boolean isUri;
private Map<String, CodegenProperty> requiredVarsMap;
private String ref;
@ -979,6 +980,10 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
public void setIsUuid(boolean isUuid) { this.isUuid = isUuid; }
public boolean getIsUri() { return isUri; }
public void setIsUri(boolean isUri) { this.isUri = isUri; }
@Override
public void setComposedSchemas(CodegenComposedSchemas composedSchemas) {
this.composedSchemas = composedSchemas;
@ -1112,6 +1117,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
hasMultipleTypes == that.getHasMultipleTypes() &&
hasDiscriminatorWithNonEmptyMapping == that.getHasDiscriminatorWithNonEmptyMapping() &&
isUuid == that.getIsUuid() &&
isUri == that.getIsUri() &&
isBooleanSchemaTrue == that.getIsBooleanSchemaTrue() &&
isBooleanSchemaFalse == that.getIsBooleanSchemaFalse() &&
getSchemaIsFromAdditionalProperties() == that.getSchemaIsFromAdditionalProperties() &&
@ -1199,7 +1205,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
getMinItems(), getMaxLength(), getMinLength(), getExclusiveMinimum(), getExclusiveMaximum(), getMinimum(),
getMaximum(), getPattern(), getMultipleOf(), getItems(), getAdditionalProperties(), getIsModel(),
getAdditionalPropertiesIsAnyType(), hasDiscriminatorWithNonEmptyMapping,
isAnyType, getComposedSchemas(), hasMultipleTypes, isDecimal, isUuid, requiredVarsMap, ref,
isAnyType, getComposedSchemas(), hasMultipleTypes, isDecimal, isUuid, isUri, requiredVarsMap, ref,
uniqueItemsBoolean, schemaIsFromAdditionalProperties, isBooleanSchemaTrue, isBooleanSchemaFalse,
format, dependentRequired, contains);
}
@ -1300,6 +1306,7 @@ public class CodegenModel implements IJsonSchemaValidationProperties {
sb.append(", hasMultipleTypes=").append(hasMultipleTypes);
sb.append(", isDecimal=").append(isDecimal);
sb.append(", isUUID=").append(isUuid);
sb.append(", isURI=").append(isUri);
sb.append(", requiredVarsMap=").append(requiredVarsMap);
sb.append(", ref=").append(ref);
sb.append(", schemaIsFromAdditionalProperties=").append(schemaIsFromAdditionalProperties);

View File

@ -3051,6 +3051,9 @@ public class DefaultCodegen implements CodegenConfig {
// NOTE: UUID schemas as CodegenModel is a rare use case and may be removed at a later date.
model.setIsString(false);
model.setIsUuid(true);
} else if (ModelUtils.isURISchema(schema)) {
model.setIsString(false);
model.setIsUri(true);
}
}

View File

@ -15,7 +15,7 @@
{{#enumVars}}@XmlEnumValue({{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}{{{value}}}{{#isInteger}}"{{/isInteger}}{{#isDouble}}"{{/isDouble}}{{#isLong}}"{{/isLong}}{{#isFloat}}"{{/isFloat}}) {{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}
{{/withXml}}
{{^withXml}}
{{#enumVars}}{{name}}({{dataType}}.valueOf({{{value}}})){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}
{{#enumVars}}{{name}}({{^isUri}}{{dataType}}.valueOf({{/isUri}}{{{value}}}{{^isUri}}){{/isUri}}){{^-last}}, {{/-last}}{{#-last}};{{/-last}}{{/enumVars}}
{{/withXml}}
{{/allowableValues}}
@ -65,7 +65,7 @@
public static final class Serializer implements JsonbSerializer<{{datatypeWithEnum}}> {
@Override
public void serialize({{datatypeWithEnum}} obj, JsonGenerator generator, SerializationContext ctx) {
generator.write(obj.value);
generator.write(obj.value{{#isUri}}.toASCIIString(){{/isUri}});
}
}
{{/jsonb}}

View File

@ -2,6 +2,9 @@
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
{{/jackson}}
{{#isUri}}
import java.net.URI;
{{/isUri}}
/**
* {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}

View File

@ -9,6 +9,9 @@ import com.google.gson.annotations.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
{{/gson}}
{{#isUri}}
import java.net.URI;
{{/isUri}}
/**
* {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}

View File

@ -1,4 +1,7 @@
import java.io.IOException;
{{#isUri}}
import java.net.URI;
{{/isUri}}
import com.google.gson.TypeAdapter;
import com.google.gson.JsonElement;
import com.google.gson.annotations.JsonAdapter;
@ -49,18 +52,18 @@ import com.google.gson.stream.JsonWriter;
public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> {
@Override
public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException {
jsonWriter.value(enumeration.getValue());
jsonWriter.value(enumeration.getValue(){{#isUri}}.toASCIIString(){{/isUri}});
}
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}}{{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
public static void validateJsonElement(JsonElement jsonElement) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}getAs{{{dataType}}}(){{/isInteger}}{{/isNumber}};
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isUri}}URI.create({{/isUri}}jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{#isUri}}getAsString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}getAs{{{dataType}}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
{{#supportUrlQuery}}

View File

@ -49,18 +49,18 @@
public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> {
@Override
public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException {
jsonWriter.value(enumeration.getValue());
jsonWriter.value(enumeration.getValue(){{#isUri}}.toASCIIString(){{/isUri}});
}
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isInteger}}{{/isNumber}};
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} {{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
public static void validateJsonElement(JsonElement jsonElement) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}getAs{{{dataType}}}(){{/isInteger}}{{/isNumber}};
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isUri}}URI.create({{/isUri}}jsonElement.{{#isNumber}}getAsString(){{/isNumber}}{{#isInteger}}getAsInt(){{/isInteger}}{{#isUri}}getAsString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}getAs{{{dataType}}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}

View File

@ -9,6 +9,9 @@ import com.google.gson.annotations.JsonAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
{{/gson}}
{{#isUri}}
import java.net.URI;
{{/isUri}}
/**
* {{description}}{{^description}}Gets or Sets {{{name}}}{{/description}}
@ -67,13 +70,13 @@ import com.google.gson.stream.JsonWriter;
public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}> {
@Override
public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} enumeration) throws IOException {
jsonWriter.value(enumeration.getValue());
jsonWriter.value(enumeration.getValue(){{#isUri}}.toASCIIString(){{/isUri}});
}
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}}{{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}
{{/gson}}

View File

@ -62,12 +62,12 @@
public static class Adapter extends TypeAdapter<{{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}> {
@Override
public void write(final JsonWriter jsonWriter, final {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} enumeration) throws IOException {
jsonWriter.value(enumeration.getValue());
jsonWriter.value(enumeration.getValue(){{#isUri}}.toASCIIString(){{/isUri}});
}
@Override
public {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException {
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isInteger}}{{/isNumber}};
{{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = {{#isFloat}}(float){{/isFloat}} {{#isUri}}URI.create({{/isUri}}jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{#isUri}}nextString()){{/isUri}}{{^isNumber}}{{^isInteger}}{{^isUri}}{{#isFloat}}nextDouble{{/isFloat}}{{^isFloat}}next{{{dataType}}}{{/isFloat}}(){{/isUri}}{{/isInteger}}{{/isNumber}};
return {{{datatypeWithEnum}}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}});
}
}

View File

@ -2787,4 +2787,85 @@ public class JavaClientCodegenTest {
assertEquals(files.get("README.md"), null);
assertEquals(files.get("pom.xml"), null);
}
@Test
public void testRestTemplateHandleURIEnum() throws IOException {
String[] expectedInnerEnumLines = new String[] {
"V1_SCHEMA_JSON(URI.create(\"https://example.com/v1/schema.json\"))",
"V2_SCHEMA_JSON(URI.create(\"https://example.com/v2/schema.json\"))"
};
String[] expectedEnumLines = new String[] {
"V1_METADATA_JSON(URI.create(\"https://example.com/v1/metadata.json\"))",
"V2_METADATA_JSON(URI.create(\"https://example.com/v2/metadata.json\"))"
};
testHandleURIEnum(JavaClientCodegen.RESTTEMPLATE, expectedInnerEnumLines, expectedEnumLines);
}
@Test
public void testOkHttpGsonHandleURIEnum() throws IOException {
String[] expectedInnerEnumLines = new String[] {
"V1_SCHEMA_JSON(URI.create(\"https://example.com/v1/schema.json\"))",
"V2_SCHEMA_JSON(URI.create(\"https://example.com/v2/schema.json\"))",
"jsonWriter.value(enumeration.getValue().toASCIIString())",
"URI value = URI.create(jsonReader.nextString())",
"URI value = URI.create(jsonElement.getAsString())"
};
String[] expectedEnumLines = new String[] {
"V1_METADATA_JSON(URI.create(\"https://example.com/v1/metadata.json\"))",
"V2_METADATA_JSON(URI.create(\"https://example.com/v2/metadata.json\"))",
"jsonWriter.value(enumeration.getValue().toASCIIString())",
"URI value = URI.create(jsonReader.nextString())",
"URI value = URI.create(jsonElement.getAsString())"
};
testHandleURIEnum(JavaClientCodegen.OKHTTP_GSON, expectedInnerEnumLines, expectedEnumLines);
}
@Test
public void testMicroprofileHandleURIEnum() throws IOException {
String[] expectedInnerEnumLines = new String[] {
"V1_SCHEMA_JSON(URI.create(\"https://example.com/v1/schema.json\"))",
"V2_SCHEMA_JSON(URI.create(\"https://example.com/v2/schema.json\"))",
"generator.write(obj.value.toASCIIString())"
};
String[] expectedEnumLines = new String[] {
"V1_METADATA_JSON(URI.create(\"https://example.com/v1/metadata.json\"))",
"V2_METADATA_JSON(URI.create(\"https://example.com/v2/metadata.json\"))"
};
testHandleURIEnum(JavaClientCodegen.MICROPROFILE, expectedInnerEnumLines, expectedEnumLines);
}
private void testHandleURIEnum(String library, String[] expectedInnerEnumLines, String[] expectedEnumLines) throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
output.deleteOnExit();
final CodegenConfigurator configurator = new CodegenConfigurator()
.setGeneratorName("java")
.setLibrary(library)
.setInputSpec("src/test/resources/3_0/enum-and-inner-enum-uri.yaml")
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
final ClientOptInput clientOptInput = configurator.toClientOptInput();
final DefaultGenerator defaultGenerator = new DefaultGenerator();
defaultGenerator.opts(clientOptInput);
Map<String, File> files = defaultGenerator.generate().stream()
.collect(Collectors.toMap(File::getName, Function.identity()));
// enum
File modelFile = files.get("Metadata.java");
assertNotNull(modelFile);
JavaFileAssert.assertThat(modelFile).fileContains(expectedEnumLines);
// Inner enum
File apiFile = files.get("V1SchemasGetDefaultResponse.java");
assertNotNull(apiFile);
JavaFileAssert.assertThat(apiFile).fileContains(expectedInnerEnumLines);
}
}

View File

@ -0,0 +1,38 @@
openapi: 3.0.3
info:
title: Example API
description: ''
version: v1
servers:
- url: http://localhost
description: Global Endpoint
paths:
/v1/schemas:
get:
summary: Get a list of schemas
responses:
default:
description: List of schemas
content:
application/json:
schema:
type: object
properties:
data:
type: string
format: uri
default: https://example.com/v1/schema.json
enum:
- https://example.com/v1/schema.json
- https://example.com/v2/schema.json
metadata:
$ref: '#/components/schemas/Metadata'
components:
schemas:
Metadata:
type: string
format: uri
enum:
- https://example.com/v1/metadata.json
- https://example.com/v2/metadata.json