diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java index d396acc8566f..39537dfc4b9c 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java @@ -803,6 +803,13 @@ public class OpenAPINormalizer { * @param schema Schema */ protected void normalizeReferenceSchema(Schema schema) { + if (schema.getType() != null || schema.getTypes() != null && !schema.getTypes().isEmpty()) { + // clears type(s) given that $ref is set + schema.setType(null); + schema.setTypes(null); + LOGGER.warn("Type(s) cleared (set to null) given $ref is set to {}.", schema.get$ref()); + } + if (schema.getTitle() != null || schema.getDescription() != null || schema.getNullable() != null || schema.getDefault() != null || schema.getDeprecated() != null || schema.getMaximum() != null || schema.getMinimum() != null diff --git a/modules/openapi-generator/src/test/resources/3_1/java/petstore.yaml b/modules/openapi-generator/src/test/resources/3_1/java/petstore.yaml index 44ccd02645fc..0b5d6425f40e 100644 --- a/modules/openapi-generator/src/test/resources/3_1/java/petstore.yaml +++ b/modules/openapi-generator/src/test/resources/3_1/java/petstore.yaml @@ -1117,3 +1117,11 @@ components: properties: dummy: type: string + PetWithTypesObjectNullAndRef: + type: object + properties: + first_property: + type: + - "object" + - "null" + $ref: '#/components/schemas/Pet' diff --git a/samples/client/petstore/java/okhttp-gson-3.1/.openapi-generator/FILES b/samples/client/petstore/java/okhttp-gson-3.1/.openapi-generator/FILES index 0f5e9fcaaa55..82d51ff39be6 100644 --- a/samples/client/petstore/java/okhttp-gson-3.1/.openapi-generator/FILES +++ b/samples/client/petstore/java/okhttp-gson-3.1/.openapi-generator/FILES @@ -25,6 +25,7 @@ docs/OneOfStringOrInt.md docs/Order.md docs/Pet.md docs/PetApi.md +docs/PetWithTypesObjectNullAndRef.md docs/RefRefToPathLevelParameterOneofRefToOneofParameter.md docs/RefToRefParameterAnyofRefToAnyofParameter.md docs/SelfReferenceAdditionalProperties.md @@ -89,6 +90,7 @@ src/main/java/org/openapitools/client/model/ModelApiResponse.java src/main/java/org/openapitools/client/model/OneOfStringOrInt.java src/main/java/org/openapitools/client/model/Order.java src/main/java/org/openapitools/client/model/Pet.java +src/main/java/org/openapitools/client/model/PetWithTypesObjectNullAndRef.java src/main/java/org/openapitools/client/model/RefRefToPathLevelParameterOneofRefToOneofParameter.java src/main/java/org/openapitools/client/model/RefToRefParameterAnyofRefToAnyofParameter.java src/main/java/org/openapitools/client/model/SelfReferenceAdditionalProperties.java diff --git a/samples/client/petstore/java/okhttp-gson-3.1/README.md b/samples/client/petstore/java/okhttp-gson-3.1/README.md index be263923550e..f44b2376dcf6 100644 --- a/samples/client/petstore/java/okhttp-gson-3.1/README.md +++ b/samples/client/petstore/java/okhttp-gson-3.1/README.md @@ -166,6 +166,7 @@ Class | Method | HTTP request | Description - [OneOfStringOrInt](docs/OneOfStringOrInt.md) - [Order](docs/Order.md) - [Pet](docs/Pet.md) + - [PetWithTypesObjectNullAndRef](docs/PetWithTypesObjectNullAndRef.md) - [RefRefToPathLevelParameterOneofRefToOneofParameter](docs/RefRefToPathLevelParameterOneofRefToOneofParameter.md) - [RefToRefParameterAnyofRefToAnyofParameter](docs/RefToRefParameterAnyofRefToAnyofParameter.md) - [SelfReferenceAdditionalProperties](docs/SelfReferenceAdditionalProperties.md) diff --git a/samples/client/petstore/java/okhttp-gson-3.1/api/openapi.yaml b/samples/client/petstore/java/okhttp-gson-3.1/api/openapi.yaml index 9d15c38d5d60..143fc0a336ce 100644 --- a/samples/client/petstore/java/okhttp-gson-3.1/api/openapi.yaml +++ b/samples/client/petstore/java/okhttp-gson-3.1/api/openapi.yaml @@ -1182,6 +1182,10 @@ components: properties: dummy: type: string + PetWithTypesObjectNullAndRef: + properties: + first_property: + $ref: "#/components/schemas/Pet" updatePetWithForm_request: properties: name: diff --git a/samples/client/petstore/java/okhttp-gson-3.1/docs/PetWithTypesObjectNullAndRef.md b/samples/client/petstore/java/okhttp-gson-3.1/docs/PetWithTypesObjectNullAndRef.md new file mode 100644 index 000000000000..618d36cc0b19 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-3.1/docs/PetWithTypesObjectNullAndRef.md @@ -0,0 +1,13 @@ + + +# PetWithTypesObjectNullAndRef + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**firstProperty** | [**Pet**](Pet.md) | | [optional] | + + + diff --git a/samples/client/petstore/java/okhttp-gson-3.1/src/main/java/org/openapitools/client/JSON.java b/samples/client/petstore/java/okhttp-gson-3.1/src/main/java/org/openapitools/client/JSON.java index 4b5391a85918..67cd90e25b1e 100644 --- a/samples/client/petstore/java/okhttp-gson-3.1/src/main/java/org/openapitools/client/JSON.java +++ b/samples/client/petstore/java/okhttp-gson-3.1/src/main/java/org/openapitools/client/JSON.java @@ -140,6 +140,7 @@ public class JSON { gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.OneOfStringOrInt.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Order.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Pet.CustomTypeAdapterFactory()); + gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.PetWithTypesObjectNullAndRef.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.RefRefToPathLevelParameterOneofRefToOneofParameter.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.RefToRefParameterAnyofRefToAnyofParameter.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.SelfReferenceAdditionalProperties.CustomTypeAdapterFactory()); diff --git a/samples/client/petstore/java/okhttp-gson-3.1/src/main/java/org/openapitools/client/model/PetWithTypesObjectNullAndRef.java b/samples/client/petstore/java/okhttp-gson-3.1/src/main/java/org/openapitools/client/model/PetWithTypesObjectNullAndRef.java new file mode 100644 index 000000000000..bc8fddecbe01 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-3.1/src/main/java/org/openapitools/client/model/PetWithTypesObjectNullAndRef.java @@ -0,0 +1,288 @@ +/* + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.openapitools.client.model; + +import java.util.Objects; +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.Arrays; +import org.openapitools.client.model.Pet; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.openapitools.client.JSON; + +/** + * PetWithTypesObjectNullAndRef + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.20.0-SNAPSHOT") +public class PetWithTypesObjectNullAndRef { + public static final String SERIALIZED_NAME_FIRST_PROPERTY = "first_property"; + @SerializedName(SERIALIZED_NAME_FIRST_PROPERTY) + @javax.annotation.Nullable + private Pet firstProperty; + + public PetWithTypesObjectNullAndRef() { + } + + public PetWithTypesObjectNullAndRef firstProperty(@javax.annotation.Nullable Pet firstProperty) { + this.firstProperty = firstProperty; + return this; + } + + /** + * Get firstProperty + * @return firstProperty + */ + @javax.annotation.Nullable + public Pet getFirstProperty() { + return firstProperty; + } + + public void setFirstProperty(@javax.annotation.Nullable Pet firstProperty) { + this.firstProperty = firstProperty; + } + + /** + * A container for additional, undeclared properties. + * This is a holder for any undeclared properties as specified with + * the 'additionalProperties' keyword in the OAS document. + */ + private Map additionalProperties; + + /** + * Set the additional (undeclared) property with the specified name and value. + * If the property does not already exist, create it otherwise replace it. + * + * @param key name of the property + * @param value value of the property + * @return the PetWithTypesObjectNullAndRef instance itself + */ + public PetWithTypesObjectNullAndRef putAdditionalProperty(String key, Object value) { + if (this.additionalProperties == null) { + this.additionalProperties = new HashMap(); + } + this.additionalProperties.put(key, value); + return this; + } + + /** + * Return the additional (undeclared) property. + * + * @return a map of objects + */ + public Map getAdditionalProperties() { + return additionalProperties; + } + + /** + * Return the additional (undeclared) property with the specified name. + * + * @param key name of the property + * @return an object + */ + public Object getAdditionalProperty(String key) { + if (this.additionalProperties == null) { + return null; + } + return this.additionalProperties.get(key); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PetWithTypesObjectNullAndRef petWithTypesObjectNullAndRef = (PetWithTypesObjectNullAndRef) o; + return Objects.equals(this.firstProperty, petWithTypesObjectNullAndRef.firstProperty)&& + Objects.equals(this.additionalProperties, petWithTypesObjectNullAndRef.additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(firstProperty, additionalProperties); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class PetWithTypesObjectNullAndRef {\n"); + sb.append(" firstProperty: ").append(toIndentedString(firstProperty)).append("\n"); + sb.append(" additionalProperties: ").append(toIndentedString(additionalProperties)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + + public static HashSet openapiFields; + public static HashSet openapiRequiredFields; + + static { + // a set of all properties/fields (JSON key names) + openapiFields = new HashSet(Arrays.asList("first_property")); + + // a set of required properties/fields (JSON key names) + openapiRequiredFields = new HashSet(0); + } + + /** + * Validates the JSON Element and throws an exception if issues found + * + * @param jsonElement JSON Element + * @throws IOException if the JSON Element is invalid with respect to PetWithTypesObjectNullAndRef + */ + public static void validateJsonElement(JsonElement jsonElement) throws IOException { + if (jsonElement == null) { + if (!PetWithTypesObjectNullAndRef.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The required field(s) %s in PetWithTypesObjectNullAndRef is not found in the empty JSON string", PetWithTypesObjectNullAndRef.openapiRequiredFields.toString())); + } + } + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // validate the optional field `first_property` + if (jsonObj.get("first_property") != null && !jsonObj.get("first_property").isJsonNull()) { + Pet.validateJsonElement(jsonObj.get("first_property")); + } + } + + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!PetWithTypesObjectNullAndRef.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes 'PetWithTypesObjectNullAndRef' and its subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + final TypeAdapter thisAdapter + = gson.getDelegateAdapter(this, TypeToken.get(PetWithTypesObjectNullAndRef.class)); + + return (TypeAdapter) new TypeAdapter() { + @Override + public void write(JsonWriter out, PetWithTypesObjectNullAndRef value) throws IOException { + JsonObject obj = thisAdapter.toJsonTree(value).getAsJsonObject(); + obj.remove("additionalProperties"); + // serialize additional properties + if (value.getAdditionalProperties() != null) { + for (Map.Entry entry : value.getAdditionalProperties().entrySet()) { + if (entry.getValue() instanceof String) + obj.addProperty(entry.getKey(), (String) entry.getValue()); + else if (entry.getValue() instanceof Number) + obj.addProperty(entry.getKey(), (Number) entry.getValue()); + else if (entry.getValue() instanceof Boolean) + obj.addProperty(entry.getKey(), (Boolean) entry.getValue()); + else if (entry.getValue() instanceof Character) + obj.addProperty(entry.getKey(), (Character) entry.getValue()); + else { + JsonElement jsonElement = gson.toJsonTree(entry.getValue()); + if (jsonElement.isJsonArray()) { + obj.add(entry.getKey(), jsonElement.getAsJsonArray()); + } else { + obj.add(entry.getKey(), jsonElement.getAsJsonObject()); + } + } + } + } + elementAdapter.write(out, obj); + } + + @Override + public PetWithTypesObjectNullAndRef read(JsonReader in) throws IOException { + JsonElement jsonElement = elementAdapter.read(in); + validateJsonElement(jsonElement); + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // store additional fields in the deserialized instance + PetWithTypesObjectNullAndRef instance = thisAdapter.fromJsonTree(jsonObj); + for (Map.Entry entry : jsonObj.entrySet()) { + if (!openapiFields.contains(entry.getKey())) { + if (entry.getValue().isJsonPrimitive()) { // primitive type + if (entry.getValue().getAsJsonPrimitive().isString()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsString()); + else if (entry.getValue().getAsJsonPrimitive().isNumber()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsNumber()); + else if (entry.getValue().getAsJsonPrimitive().isBoolean()) + instance.putAdditionalProperty(entry.getKey(), entry.getValue().getAsBoolean()); + else + throw new IllegalArgumentException(String.format(java.util.Locale.ROOT, "The field `%s` has unknown primitive type. Value: %s", entry.getKey(), entry.getValue().toString())); + } else if (entry.getValue().isJsonArray()) { + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), List.class)); + } else { // JSON object + instance.putAdditionalProperty(entry.getKey(), gson.fromJson(entry.getValue(), HashMap.class)); + } + } + } + return instance; + } + + }.nullSafe(); + } + } + + /** + * Create an instance of PetWithTypesObjectNullAndRef given an JSON string + * + * @param jsonString JSON string + * @return An instance of PetWithTypesObjectNullAndRef + * @throws IOException if the JSON string is invalid with respect to PetWithTypesObjectNullAndRef + */ + public static PetWithTypesObjectNullAndRef fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, PetWithTypesObjectNullAndRef.class); + } + + /** + * Convert an instance of PetWithTypesObjectNullAndRef to an JSON string + * + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } +} + diff --git a/samples/client/petstore/java/okhttp-gson-3.1/src/test/java/org/openapitools/client/model/PetWithTypesObjectNullAndRefTest.java b/samples/client/petstore/java/okhttp-gson-3.1/src/test/java/org/openapitools/client/model/PetWithTypesObjectNullAndRefTest.java new file mode 100644 index 000000000000..d9c1b8ab9eb4 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson-3.1/src/test/java/org/openapitools/client/model/PetWithTypesObjectNullAndRefTest.java @@ -0,0 +1,49 @@ +/* + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.openapitools.client.model; + +import com.google.gson.TypeAdapter; +import com.google.gson.annotations.JsonAdapter; +import com.google.gson.annotations.SerializedName; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import java.io.IOException; +import java.util.Arrays; +import org.openapitools.client.model.Pet; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +/** + * Model tests for PetWithTypesObjectNullAndRef + */ +public class PetWithTypesObjectNullAndRefTest { + private final PetWithTypesObjectNullAndRef model = new PetWithTypesObjectNullAndRef(); + + /** + * Model tests for PetWithTypesObjectNullAndRef + */ + @Test + public void testPetWithTypesObjectNullAndRef() { + // TODO: test PetWithTypesObjectNullAndRef + } + + /** + * Test the property 'firstProperty' + */ + @Test + public void firstPropertyTest() { + // TODO: test firstProperty + } + +}