diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index 733ba2bced99..fef3a3824cb7 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -1291,6 +1291,9 @@ public String toArrayDefaultValue(CodegenProperty cp, Schema schema) { } }) .collect(Collectors.joining(", ")); + } else if (cp.items.isContainer) { + // TODO nested array/set/map is not supported at the moment so defaulting to null + defaultValue = null; } else { // array item is non-string, e.g. integer defaultValue = StringUtils.join(_values, ", "); } diff --git a/modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml b/modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml index 3d6fb0e9be22..f4c8dad31d24 100644 --- a/modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/java/petstore-with-fake-endpoints-models-for-testing-okhttp-gson.yaml @@ -2809,3 +2809,20 @@ components: $ref: '#/components/schemas/ArrayOneOf' anyof_prop: $ref: '#/components/schemas/ArrayAnyOf' + NestedArrayWithDefaultValues: + type: object + properties: + nestedArray: + type: array + items: + type: array + items: + type: string + default: ["value1", "value2"] + default: + [ + [ "h1", "Header 1" ], + [ "h2", "Header 2" ], + [ "h3", "Header 3" ], + [ "h4", "Header 4" ] + ] diff --git a/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES b/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES index 9f59b5c1b8a2..25b82e9f3dd7 100644 --- a/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES +++ b/samples/client/petstore/java/okhttp-gson/.openapi-generator/FILES @@ -71,6 +71,7 @@ docs/ModelList.md docs/ModelReturn.md docs/ModelWithOneOfAnyOfProperties.md docs/Name.md +docs/NestedArrayWithDefaultValues.md docs/NewPet.md docs/NewPetCategoryInlineAllof.md docs/NewPetCategoryInlineAllofAllOfCategoryTag.md @@ -216,6 +217,7 @@ src/main/java/org/openapitools/client/model/ModelList.java src/main/java/org/openapitools/client/model/ModelReturn.java src/main/java/org/openapitools/client/model/ModelWithOneOfAnyOfProperties.java src/main/java/org/openapitools/client/model/Name.java +src/main/java/org/openapitools/client/model/NestedArrayWithDefaultValues.java src/main/java/org/openapitools/client/model/NewPet.java src/main/java/org/openapitools/client/model/NewPetCategoryInlineAllof.java src/main/java/org/openapitools/client/model/NewPetCategoryInlineAllofAllOfCategoryTag.java diff --git a/samples/client/petstore/java/okhttp-gson/README.md b/samples/client/petstore/java/okhttp-gson/README.md index 4ad62ce26a95..6c9b522d16a8 100644 --- a/samples/client/petstore/java/okhttp-gson/README.md +++ b/samples/client/petstore/java/okhttp-gson/README.md @@ -233,6 +233,7 @@ Class | Method | HTTP request | Description - [ModelReturn](docs/ModelReturn.md) - [ModelWithOneOfAnyOfProperties](docs/ModelWithOneOfAnyOfProperties.md) - [Name](docs/Name.md) + - [NestedArrayWithDefaultValues](docs/NestedArrayWithDefaultValues.md) - [NewPet](docs/NewPet.md) - [NewPetCategoryInlineAllof](docs/NewPetCategoryInlineAllof.md) - [NewPetCategoryInlineAllofAllOfCategoryTag](docs/NewPetCategoryInlineAllofAllOfCategoryTag.md) diff --git a/samples/client/petstore/java/okhttp-gson/api/openapi.yaml b/samples/client/petstore/java/okhttp-gson/api/openapi.yaml index 84cc46562f5a..c0ff5254e610 100644 --- a/samples/client/petstore/java/okhttp-gson/api/openapi.yaml +++ b/samples/client/petstore/java/okhttp-gson/api/openapi.yaml @@ -2916,6 +2916,27 @@ components: anyof_prop: $ref: "#/components/schemas/ArrayAnyOf" type: object + NestedArrayWithDefaultValues: + properties: + nestedArray: + default: + - - h1 + - Header 1 + - - h2 + - Header 2 + - - h3 + - Header 3 + - - h4 + - Header 4 + items: + default: + - value1 + - value2 + items: + type: string + type: array + type: array + type: object _foo_get_default_response: example: string: diff --git a/samples/client/petstore/java/okhttp-gson/docs/NestedArrayWithDefaultValues.md b/samples/client/petstore/java/okhttp-gson/docs/NestedArrayWithDefaultValues.md new file mode 100644 index 000000000000..c5f272f1cb30 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/docs/NestedArrayWithDefaultValues.md @@ -0,0 +1,13 @@ + + +# NestedArrayWithDefaultValues + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**nestedArray** | **List<List<String>>** | | [optional] | + + + diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/JSON.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/JSON.java index 0a0d4e1c4b71..206faee941f3 100644 --- a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/JSON.java +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/JSON.java @@ -303,6 +303,7 @@ private static Class getClassByDiscriminator(Map classByDiscriminatorValue, Stri gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.ModelReturn.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.ModelWithOneOfAnyOfProperties.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.Name.CustomTypeAdapterFactory()); + gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.NestedArrayWithDefaultValues.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.NewPet.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.NewPetCategoryInlineAllof.CustomTypeAdapterFactory()); gsonBuilder.registerTypeAdapterFactory(new org.openapitools.client.model.NewPetCategoryInlineAllofAllOfCategoryTag.CustomTypeAdapterFactory()); diff --git a/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NestedArrayWithDefaultValues.java b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NestedArrayWithDefaultValues.java new file mode 100644 index 000000000000..7322b8e6417c --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/main/java/org/openapitools/client/model/NestedArrayWithDefaultValues.java @@ -0,0 +1,297 @@ +/* + * OpenAPI Petstore + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ + * + * 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.ArrayList; +import java.util.Arrays; +import java.util.List; + +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; + +/** + * NestedArrayWithDefaultValues + */ +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.15.0-SNAPSHOT") +public class NestedArrayWithDefaultValues { + public static final String SERIALIZED_NAME_NESTED_ARRAY = "nestedArray"; + @SerializedName(SERIALIZED_NAME_NESTED_ARRAY) + @javax.annotation.Nullable + private List> nestedArray; + + public NestedArrayWithDefaultValues() { + } + + public NestedArrayWithDefaultValues nestedArray(@javax.annotation.Nullable List> nestedArray) { + this.nestedArray = nestedArray; + return this; + } + + public NestedArrayWithDefaultValues addNestedArrayItem(List nestedArrayItem) { + if (this.nestedArray == null) { + this.nestedArray = new ArrayList<>(); + } + this.nestedArray.add(nestedArrayItem); + return this; + } + + /** + * Get nestedArray + * @return nestedArray + */ + @javax.annotation.Nullable + public List> getNestedArray() { + return nestedArray; + } + + public void setNestedArray(@javax.annotation.Nullable List> nestedArray) { + this.nestedArray = nestedArray; + } + + /** + * 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 NestedArrayWithDefaultValues instance itself + */ + public NestedArrayWithDefaultValues 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; + } + NestedArrayWithDefaultValues nestedArrayWithDefaultValues = (NestedArrayWithDefaultValues) o; + return Objects.equals(this.nestedArray, nestedArrayWithDefaultValues.nestedArray)&& + Objects.equals(this.additionalProperties, nestedArrayWithDefaultValues.additionalProperties); + } + + @Override + public int hashCode() { + return Objects.hash(nestedArray, additionalProperties); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class NestedArrayWithDefaultValues {\n"); + sb.append(" nestedArray: ").append(toIndentedString(nestedArray)).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("nestedArray")); + + // 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 NestedArrayWithDefaultValues + */ + public static void validateJsonElement(JsonElement jsonElement) throws IOException { + if (jsonElement == null) { + if (!NestedArrayWithDefaultValues.openapiRequiredFields.isEmpty()) { // has required fields but JSON element is null + throw new IllegalArgumentException(String.format("The required field(s) %s in NestedArrayWithDefaultValues is not found in the empty JSON string", NestedArrayWithDefaultValues.openapiRequiredFields.toString())); + } + } + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // ensure the optional json data is an array if present + if (jsonObj.get("nestedArray") != null && !jsonObj.get("nestedArray").isJsonNull() && !jsonObj.get("nestedArray").isJsonArray()) { + throw new IllegalArgumentException(String.format("Expected the field `nestedArray` to be an array in the JSON string but got `%s`", jsonObj.get("nestedArray").toString())); + } + } + + public static class CustomTypeAdapterFactory implements TypeAdapterFactory { + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!NestedArrayWithDefaultValues.class.isAssignableFrom(type.getRawType())) { + return null; // this class only serializes 'NestedArrayWithDefaultValues' and its subtypes + } + final TypeAdapter elementAdapter = gson.getAdapter(JsonElement.class); + final TypeAdapter thisAdapter + = gson.getDelegateAdapter(this, TypeToken.get(NestedArrayWithDefaultValues.class)); + + return (TypeAdapter) new TypeAdapter() { + @Override + public void write(JsonWriter out, NestedArrayWithDefaultValues 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 NestedArrayWithDefaultValues read(JsonReader in) throws IOException { + JsonElement jsonElement = elementAdapter.read(in); + validateJsonElement(jsonElement); + JsonObject jsonObj = jsonElement.getAsJsonObject(); + // store additional fields in the deserialized instance + NestedArrayWithDefaultValues 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("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 NestedArrayWithDefaultValues given an JSON string + * + * @param jsonString JSON string + * @return An instance of NestedArrayWithDefaultValues + * @throws IOException if the JSON string is invalid with respect to NestedArrayWithDefaultValues + */ + public static NestedArrayWithDefaultValues fromJson(String jsonString) throws IOException { + return JSON.getGson().fromJson(jsonString, NestedArrayWithDefaultValues.class); + } + + /** + * Convert an instance of NestedArrayWithDefaultValues to an JSON string + * + * @return JSON string + */ + public String toJson() { + return JSON.getGson().toJson(this); + } +} + diff --git a/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/model/NestedArrayWithDefaultValuesTest.java b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/model/NestedArrayWithDefaultValuesTest.java new file mode 100644 index 000000000000..417d2f5d90f2 --- /dev/null +++ b/samples/client/petstore/java/okhttp-gson/src/test/java/org/openapitools/client/model/NestedArrayWithDefaultValuesTest.java @@ -0,0 +1,50 @@ +/* + * OpenAPI Petstore + * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\ + * + * 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.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +/** + * Model tests for NestedArrayWithDefaultValues + */ +public class NestedArrayWithDefaultValuesTest { + private final NestedArrayWithDefaultValues model = new NestedArrayWithDefaultValues(); + + /** + * Model tests for NestedArrayWithDefaultValues + */ + @Test + public void testNestedArrayWithDefaultValues() { + // TODO: test NestedArrayWithDefaultValues + } + + /** + * Test the property 'nestedArray' + */ + @Test + public void nestedArrayTest() { + // TODO: test nestedArray + } + +}