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 f75cb1fbef3c..042c7e6b0fb3 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 @@ -36,6 +36,7 @@ import java.util.function.Function; import java.util.stream.Collectors; +import static org.openapitools.codegen.utils.ModelUtils.simplyOneOfAnyOfWithOnlyOneNonNullSubSchema; import static org.openapitools.codegen.utils.StringUtils.getUniqueString; public class OpenAPINormalizer { @@ -1213,17 +1214,7 @@ private Schema processSimplifyOneOf(Schema schema) { } } - if (oneOfSchemas.removeIf(oneOf -> ModelUtils.isNullTypeSchema(openAPI, oneOf))) { - schema.setNullable(true); - - // if only one element left, simplify to just the element (schema) - if (oneOfSchemas.size() == 1) { - if (Boolean.TRUE.equals(schema.getNullable())) { // retain nullable setting - ((Schema) oneOfSchemas.get(0)).setNullable(true); - } - return (Schema) oneOfSchemas.get(0); - } - } + schema = simplyOneOfAnyOfWithOnlyOneNonNullSubSchema(openAPI, schema, oneOfSchemas); if (ModelUtils.isIntegerSchema(schema) || ModelUtils.isNumberSchema(schema) || ModelUtils.isStringSchema(schema)) { // TODO convert oneOf const to enum @@ -1350,17 +1341,7 @@ private Schema processSimplifyAnyOf(Schema schema) { } } - if (anyOfSchemas.removeIf(anyOf -> ModelUtils.isNullTypeSchema(openAPI, anyOf))) { - schema.setNullable(true); - } - - // if only one element left, simplify to just the element (schema) - if (anyOfSchemas.size() == 1) { - if (Boolean.TRUE.equals(schema.getNullable())) { // retain nullable setting - ((Schema) anyOfSchemas.get(0)).setNullable(true); - } - return (Schema) anyOfSchemas.get(0); - } + schema = simplyOneOfAnyOfWithOnlyOneNonNullSubSchema(openAPI, schema, anyOfSchemas); } return schema; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java index 92b4330dbdda..dfa8c879f684 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java @@ -2219,6 +2219,30 @@ public static Schema cloneSchema(Schema schema, boolean openapi31) { } } + /** + * Simplifies the schema by removing the oneOfAnyOf if the oneOfAnyOf only contains a single non-null sub-schema + * + * @param openAPI OpenAPI + * @param schema Schema + * @param subSchemas The oneOf or AnyOf schemas + * @return The simplified schema + */ + public static Schema simplyOneOfAnyOfWithOnlyOneNonNullSubSchema(OpenAPI openAPI, Schema schema, List subSchemas) { + if (subSchemas.removeIf(subSchema -> isNullTypeSchema(openAPI, subSchema))) { + schema.setNullable(true); + } + + // if only one element left, simplify to just the element (schema) + if (subSchemas.size() == 1) { + if (Boolean.TRUE.equals(schema.getNullable())) { // retain nullable setting + subSchemas.get(0).setNullable(true); + } + return subSchemas.get(0); + } + + return schema; + } + /** * Check if the schema is of type 'null' or schema itself is pointing to null *

diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java index 85104bc2ea0d..5b2ba7abb2e6 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/OpenAPINormalizerTest.java @@ -24,10 +24,7 @@ import org.openapitools.codegen.utils.ModelUtils; import org.testng.annotations.Test; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import static org.testng.Assert.*; @@ -171,6 +168,12 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf() { Schema schema15 = openAPI.getComponents().getSchemas().get("AnyOfAnyTypeWithRef"); assertEquals(schema15.getAnyOf().size(), 6); + Schema schema17 = openAPI.getComponents().getSchemas().get("ParentWithOneOfProperty"); + assertEquals(((Schema) schema17.getProperties().get("number")).getOneOf().size(), 1); + + Schema schema19 = openAPI.getComponents().getSchemas().get("SingleAnyOfTest"); + assertEquals(schema19.getAnyOf().size(), 1); + Map options = new HashMap<>(); options.put("SIMPLIFY_ONEOF_ANYOF", "true"); OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); @@ -212,6 +215,30 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf() { Schema schema16 = openAPI.getComponents().getSchemas().get("AnyOfAnyTypeWithRef"); assertEquals(schema16.getAnyOf(), null); assertEquals(schema16.getType(), null); + + Schema schema18 = openAPI.getComponents().getSchemas().get("ParentWithOneOfProperty"); + assertEquals(((Schema) schema18.getProperties().get("number")).get$ref(), "#/components/schemas/Number"); + + Schema schema20 = openAPI.getComponents().getSchemas().get("SingleAnyOfTest"); + assertEquals(schema20.getAnyOf(), null); + assertEquals(schema20.getType(), "string"); + assertEquals(schema20.getEnum().size(), 2); + } + + @Test + public void testOpenAPINormalizerSimplifyOneOfWithSingleRef() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyOneOfAnyOf_test.yaml"); + + Schema oneOfWithSingleRef = openAPI.getComponents().getSchemas().get("ParentWithOneOfProperty"); + assertEquals(((Schema) oneOfWithSingleRef.getProperties().get("number")).getOneOf().size(), 1); + + Map options = new HashMap<>(); + options.put("SIMPLIFY_ONEOF_ANYOF", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + oneOfWithSingleRef = openAPI.getComponents().getSchemas().get("ParentWithOneOfProperty"); + assertEquals(((Schema) oneOfWithSingleRef.getProperties().get("number")).get$ref(), "#/components/schemas/Number"); } @Test @@ -833,6 +860,12 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() { Schema schema17 = openAPI.getComponents().getSchemas().get("OneOfNullAndRef3"); assertEquals(schema17.getOneOf().size(), 2); + Schema schema19 = openAPI.getComponents().getSchemas().get("ParentWithOneOfProperty"); + assertEquals(((Schema) schema19.getProperties().get("number")).getOneOf().size(), 1); + + Schema schema21 = openAPI.getComponents().getSchemas().get("SingleAnyOfTest"); + assertEquals(schema21.getAnyOf().size(), 1); + Map options = new HashMap<>(); options.put("SIMPLIFY_ONEOF_ANYOF", "true"); OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); @@ -879,6 +912,30 @@ public void testOpenAPINormalizerSimplifyOneOfAnyOf31Spec() { // original oneOf removed and simplified to just $ref (oneOf sub-schema) instead assertEquals(schema18.getOneOf(), null); assertEquals(schema18.get$ref(), "#/components/schemas/Parent"); + + Schema schema20 = openAPI.getComponents().getSchemas().get("ParentWithOneOfProperty"); + assertEquals(((Schema) schema20.getProperties().get("number")).get$ref(), "#/components/schemas/Number"); + + Schema schema22 = openAPI.getComponents().getSchemas().get("SingleAnyOfTest"); + assertEquals(schema22.getAnyOf(), null); + assertEquals(schema22.getTypes(), Set.of("string")); + assertEquals(schema22.getEnum().size(), 2); + } + + @Test + public void testOpenAPINormalizerSimplifyOneOfWithSingleRef31Spec() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_1/simplifyOneOfAnyOf_test.yaml"); + + Schema oneOfWithSingleRef = openAPI.getComponents().getSchemas().get("ParentWithOneOfProperty"); + assertEquals(((Schema) oneOfWithSingleRef.getProperties().get("number")).getOneOf().size(), 1); + + Map options = new HashMap<>(); + options.put("SIMPLIFY_ONEOF_ANYOF", "true"); + OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options); + openAPINormalizer.normalize(); + + oneOfWithSingleRef = openAPI.getComponents().getSchemas().get("ParentWithOneOfProperty"); + assertEquals(((Schema) oneOfWithSingleRef.getProperties().get("number")).get$ref(), "#/components/schemas/Number"); } @Test diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java index 921c98fee331..d5abd4df918c 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java @@ -2272,7 +2272,7 @@ public static Object[][] sealedScenarios() { "SchemaA.java", "public final class SchemaA extends RepresentationModel implements PostRequest {", "PostRequest.java", "public sealed interface PostRequest permits SchemaA {")}, {"oneOf_array.yaml", Map.of( - "MyExampleGet200Response.java", "public interface MyExampleGet200Response")}, + "MyExampleGet200Response.java", "public sealed interface MyExampleGet200Response")}, {"oneOf_duplicateArray.yaml", Map.of( "Example.java", "public interface Example {")}, {"oneOf_nonPrimitive.yaml", Map.of( diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java index 0a65c8f0879f..a0b17a447885 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/utils/ModelUtilsTest.java @@ -32,8 +32,7 @@ import java.util.List; import java.util.Map; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; +import static org.testng.Assert.*; public class ModelUtilsTest { @@ -476,6 +475,54 @@ public void testGetSchemaItemsWith31Spec() { Assert.assertNotNull(ModelUtils.getSchemaItems((Schema) arrayWithPrefixItems.getProperties().get("without_items"))); } + @Test + public void simplyOneOfAnyOfWithOnlyOneNonNullSubSchema() { + OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/simplifyOneOfAnyOf_test.yaml"); + Schema schema; + List subSchemas; + + Schema anyOfWithSeveralSubSchemasButSingleNonNull = ModelUtils.getSchema(openAPI, "AnyOfTest"); + subSchemas = anyOfWithSeveralSubSchemasButSingleNonNull.getAnyOf(); + schema = ModelUtils.simplyOneOfAnyOfWithOnlyOneNonNullSubSchema(openAPI, anyOfWithSeveralSubSchemasButSingleNonNull, subSchemas); + assertNull(schema.getOneOf()); + assertNull(schema.getAnyOf()); + assertTrue(schema.getNullable()); + assertEquals("string", schema.getType()); + + Schema anyOfWithSingleNonNullSubSchema = ModelUtils.getSchema(openAPI, "Parent"); + subSchemas = ((Schema) anyOfWithSingleNonNullSubSchema.getProperties().get("number")).getAnyOf(); + schema = ModelUtils.simplyOneOfAnyOfWithOnlyOneNonNullSubSchema(openAPI, anyOfWithSingleNonNullSubSchema, subSchemas); + assertNull(schema.getOneOf()); + assertNull(schema.getAnyOf()); + assertNull(schema.getNullable()); + assertEquals(schema.get$ref(), "#/components/schemas/Number"); + + Schema oneOfWithSeveralSubSchemasButSingleNonNull = ModelUtils.getSchema(openAPI, "OneOfTest"); + subSchemas = oneOfWithSeveralSubSchemasButSingleNonNull.getOneOf(); + schema = ModelUtils.simplyOneOfAnyOfWithOnlyOneNonNullSubSchema(openAPI, oneOfWithSeveralSubSchemasButSingleNonNull, subSchemas); + assertNull(schema.getOneOf()); + assertNull(schema.getAnyOf()); + assertTrue(schema.getNullable()); + assertEquals("integer", schema.getType()); + + Schema oneOfWithSingleNonNullSubSchema = ModelUtils.getSchema(openAPI, "ParentWithOneOfProperty"); + subSchemas = ((Schema) oneOfWithSingleNonNullSubSchema.getProperties().get("number")).getOneOf(); + schema = ModelUtils.simplyOneOfAnyOfWithOnlyOneNonNullSubSchema(openAPI, oneOfWithSingleNonNullSubSchema, subSchemas); + assertNull(schema.getOneOf()); + assertNull(schema.getAnyOf()); + assertNull(schema.getNullable()); + assertEquals(schema.get$ref(), "#/components/schemas/Number"); + + Schema oneOfWithSeveralSubSchemas = ModelUtils.getSchema(openAPI, "ParentWithPluralOneOfProperty"); + subSchemas = ((Schema) oneOfWithSeveralSubSchemas.getProperties().get("number")).getOneOf(); + schema = ModelUtils.simplyOneOfAnyOfWithOnlyOneNonNullSubSchema(openAPI, oneOfWithSeveralSubSchemas, subSchemas); + assertNull(schema.getOneOf()); + assertNotNull(oneOfWithSeveralSubSchemas.getProperties().get("number")); + assertNull(schema.getAnyOf()); + assertNull(schema.getNullable()); + assertEquals(((Schema) oneOfWithSeveralSubSchemas.getProperties().get("number")).getOneOf().size(), 2); + } + @Test public void isNullTypeSchemaTest() { OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/null_schema_test.yaml"); diff --git a/modules/openapi-generator/src/test/resources/3_0/oneOf_array.yaml b/modules/openapi-generator/src/test/resources/3_0/oneOf_array.yaml index ab98612c0b2b..72adee84e763 100644 --- a/modules/openapi-generator/src/test/resources/3_0/oneOf_array.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/oneOf_array.yaml @@ -15,6 +15,8 @@ paths: - type: array items: "$ref": "#/components/schemas/OneOf1" + - type: object + "$ref": "#/components/schemas/OneOf1" components: schemas: OneOf1: diff --git a/samples/client/others/java/okhttp-gson-oneOf-array/api/openapi.yaml b/samples/client/others/java/okhttp-gson-oneOf-array/api/openapi.yaml index e3641cf5ec56..215f2f2ff1e1 100644 --- a/samples/client/others/java/okhttp-gson-oneOf-array/api/openapi.yaml +++ b/samples/client/others/java/okhttp-gson-oneOf-array/api/openapi.yaml @@ -30,4 +30,5 @@ components: - items: $ref: '#/components/schemas/OneOf1' type: array + - $ref: '#/components/schemas/OneOf1' diff --git a/samples/client/others/java/okhttp-gson-oneOf-array/docs/MyExampleGet200Response.md b/samples/client/others/java/okhttp-gson-oneOf-array/docs/MyExampleGet200Response.md index 7396a8d1680a..4c078788ed8d 100644 --- a/samples/client/others/java/okhttp-gson-oneOf-array/docs/MyExampleGet200Response.md +++ b/samples/client/others/java/okhttp-gson-oneOf-array/docs/MyExampleGet200Response.md @@ -7,6 +7,7 @@ | Name | Type | Description | Notes | |------------ | ------------- | ------------- | -------------| +|**message1** | **String** | | [optional] | diff --git a/samples/client/others/java/okhttp-gson-oneOf-array/src/main/java/org/openapitools/client/model/MyExampleGet200Response.java b/samples/client/others/java/okhttp-gson-oneOf-array/src/main/java/org/openapitools/client/model/MyExampleGet200Response.java index 5bb39bbfab7f..7b7de2935b8d 100644 --- a/samples/client/others/java/okhttp-gson-oneOf-array/src/main/java/org/openapitools/client/model/MyExampleGet200Response.java +++ b/samples/client/others/java/okhttp-gson-oneOf-array/src/main/java/org/openapitools/client/model/MyExampleGet200Response.java @@ -14,6 +14,13 @@ 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 java.util.List; import org.openapitools.client.model.OneOf1; import javax.validation.constraints.*; @@ -69,6 +76,7 @@ public TypeAdapter create(Gson gson, TypeToken type) { final Type typeInstanceListOneOf1 = new TypeToken>(){}.getType(); final TypeAdapter> adapterListOneOf1 = (TypeAdapter>) gson.getDelegateAdapter(this, TypeToken.get(typeInstanceListOneOf1)); + final TypeAdapter adapterOneOf1 = gson.getDelegateAdapter(this, TypeToken.get(OneOf1.class)); return (TypeAdapter) new TypeAdapter() { @Override @@ -87,7 +95,13 @@ public void write(JsonWriter out, MyExampleGet200Response value) throws IOExcept return; } } - throw new IOException("Failed to serialize as the type doesn't match oneOf schemas: List<@Valid OneOf1>"); + // check if the actual instance is of the type `OneOf1` + if (value.getActualInstance() instanceof OneOf1) { + JsonElement element = adapterOneOf1.toJsonTree((OneOf1)value.getActualInstance()); + elementAdapter.write(out, element); + return; + } + throw new IOException("Failed to serialize as the type doesn't match oneOf schemas: List<@Valid OneOf1>, OneOf1"); } @Override @@ -119,6 +133,18 @@ public MyExampleGet200Response read(JsonReader in) throws IOException { errorMessages.add(String.format("Deserialization for List<@Valid OneOf1> failed with `%s`.", e.getMessage())); log.log(Level.FINER, "Input data does not match schema 'List<@Valid OneOf1>'", e); } + // deserialize OneOf1 + try { + // validate the JSON object to see if any exception is thrown + OneOf1.validateJsonElement(jsonElement); + actualAdapter = adapterOneOf1; + match++; + log.log(Level.FINER, "Input data matches schema 'OneOf1'"); + } catch (Exception e) { + // deserialization failed, continue + errorMessages.add(String.format("Deserialization for OneOf1 failed with `%s`.", e.getMessage())); + log.log(Level.FINER, "Input data does not match schema 'OneOf1'", e); + } if (match == 1) { MyExampleGet200Response ret = new MyExampleGet200Response(); @@ -146,6 +172,7 @@ public MyExampleGet200Response(Object o) { static { schemas.put("List<@Valid OneOf1>", List.class); + schemas.put("OneOf1", OneOf1.class); } @Override @@ -156,7 +183,7 @@ public Map> getSchemas() { /** * Set the instance that matches the oneOf child schema, check * the instance parameter is valid against the oneOf child schemas: - * List<@Valid OneOf1> + * List<@Valid OneOf1>, OneOf1 * * It could be an instance of the 'oneOf' schemas. */ @@ -170,14 +197,19 @@ public void setActualInstance(Object instance) { } } - throw new RuntimeException("Invalid instance type. Must be List<@Valid OneOf1>"); + if (instance instanceof OneOf1) { + super.setActualInstance(instance); + return; + } + + throw new RuntimeException("Invalid instance type. Must be List<@Valid OneOf1>, OneOf1"); } /** * Get the actual instance, which can be the following: - * List<@Valid OneOf1> + * List<@Valid OneOf1>, OneOf1 * - * @return The actual instance (List<@Valid OneOf1>) + * @return The actual instance (List<@Valid OneOf1>, OneOf1) */ @SuppressWarnings("unchecked") @Override @@ -196,6 +228,17 @@ public Object getActualInstance() { return (List<@Valid OneOf1>)super.getActualInstance(); } + /** + * Get the actual instance of `OneOf1`. If the actual instance is not `OneOf1`, + * the ClassCastException will be thrown. + * + * @return The actual instance of `OneOf1` + * @throws ClassCastException if the instance is not `OneOf1` + */ + public OneOf1 getOneOf1() throws ClassCastException { + return (OneOf1)super.getActualInstance(); + } + /** * Validates the JSON Element and throws an exception if issues found * @@ -221,8 +264,16 @@ public static void validateJsonElement(JsonElement jsonElement) throws IOExcepti errorMessages.add(String.format("Deserialization for List<@Valid OneOf1> failed with `%s`.", e.getMessage())); // continue to the next one } + // validate the json string with OneOf1 + try { + OneOf1.validateJsonElement(jsonElement); + validCount++; + } catch (Exception e) { + errorMessages.add(String.format("Deserialization for OneOf1 failed with `%s`.", e.getMessage())); + // continue to the next one + } if (validCount != 1) { - throw new IOException(String.format("The JSON string is invalid for MyExampleGet200Response with oneOf schemas: List<@Valid OneOf1>. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonElement.toString())); + throw new IOException(String.format("The JSON string is invalid for MyExampleGet200Response with oneOf schemas: List<@Valid OneOf1>, OneOf1. %d class(es) match the result, expected 1. Detailed failure message for oneOf schemas: %s. JSON: %s", validCount, errorMessages, jsonElement.toString())); } } diff --git a/samples/client/petstore/ruby-httpx/.openapi-generator/FILES b/samples/client/petstore/ruby-httpx/.openapi-generator/FILES index 937697a733e7..7bc5bf3b003e 100644 --- a/samples/client/petstore/ruby-httpx/.openapi-generator/FILES +++ b/samples/client/petstore/ruby-httpx/.openapi-generator/FILES @@ -37,7 +37,6 @@ docs/FormatTest.md docs/HasOnlyReadOnly.md docs/HealthCheckResult.md docs/List.md -docs/MamalWithEnum.md docs/Mammal.md docs/MammalAnyof.md docs/MammalWithoutDiscriminator.md @@ -108,7 +107,6 @@ lib/petstore/models/format_test.rb lib/petstore/models/has_only_read_only.rb lib/petstore/models/health_check_result.rb lib/petstore/models/list.rb -lib/petstore/models/mamal_with_enum.rb lib/petstore/models/mammal.rb lib/petstore/models/mammal_anyof.rb lib/petstore/models/mammal_without_discriminator.rb diff --git a/samples/client/petstore/ruby-httpx/README.md b/samples/client/petstore/ruby-httpx/README.md index 443714e17c78..51fdbd87c377 100644 --- a/samples/client/petstore/ruby-httpx/README.md +++ b/samples/client/petstore/ruby-httpx/README.md @@ -153,7 +153,6 @@ Class | Method | HTTP request | Description - [Petstore::HasOnlyReadOnly](docs/HasOnlyReadOnly.md) - [Petstore::HealthCheckResult](docs/HealthCheckResult.md) - [Petstore::List](docs/List.md) - - [Petstore::MamalWithEnum](docs/MamalWithEnum.md) - [Petstore::Mammal](docs/Mammal.md) - [Petstore::MammalAnyof](docs/MammalAnyof.md) - [Petstore::MammalWithoutDiscriminator](docs/MammalWithoutDiscriminator.md) diff --git a/samples/client/petstore/ruby-httpx/docs/MamalWithEnum.md b/samples/client/petstore/ruby-httpx/docs/MamalWithEnum.md deleted file mode 100644 index 37b9252a2c82..000000000000 --- a/samples/client/petstore/ruby-httpx/docs/MamalWithEnum.md +++ /dev/null @@ -1,47 +0,0 @@ -# Petstore::MamalWithEnum - -## Class instance methods - -### `openapi_one_of` - -Returns the list of classes defined in oneOf. - -#### Example - -```ruby -require 'petstore' - -Petstore::MamalWithEnum.openapi_one_of -# => -# [ -# :'Cow' -# ] -``` - -### build - -Find the appropriate object from the `openapi_one_of` list and casts the data into it. - -#### Example - -```ruby -require 'petstore' - -Petstore::MamalWithEnum.build(data) -# => # - -Petstore::MamalWithEnum.build(data_that_doesnt_match) -# => nil -``` - -#### Parameters - -| Name | Type | Description | -| ---- | ---- | ----------- | -| **data** | **Mixed** | data to be matched against the list of oneOf items | - -#### Return type - -- `Cow` -- `nil` (if no type matches) - diff --git a/samples/client/petstore/ruby-httpx/lib/petstore.rb b/samples/client/petstore/ruby-httpx/lib/petstore.rb index 9dd6adc78a2b..96ae84db16ae 100644 --- a/samples/client/petstore/ruby-httpx/lib/petstore.rb +++ b/samples/client/petstore/ruby-httpx/lib/petstore.rb @@ -42,7 +42,6 @@ require 'petstore/models/has_only_read_only' require 'petstore/models/health_check_result' require 'petstore/models/list' -require 'petstore/models/mamal_with_enum' require 'petstore/models/mammal' require 'petstore/models/mammal_anyof' require 'petstore/models/mammal_without_discriminator' diff --git a/samples/client/petstore/ruby-httpx/lib/petstore/models/mamal_with_enum.rb b/samples/client/petstore/ruby-httpx/lib/petstore/models/mamal_with_enum.rb deleted file mode 100644 index efe0f135afee..000000000000 --- a/samples/client/petstore/ruby-httpx/lib/petstore/models/mamal_with_enum.rb +++ /dev/null @@ -1,104 +0,0 @@ -=begin -#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 - -Generated by: https://openapi-generator.tech -Generator version: 7.13.0-SNAPSHOT - -=end - -require 'date' -require 'time' - -module Petstore - module MamalWithEnum - class << self - # List of class defined in oneOf (OpenAPI v3) - def openapi_one_of - [ - :'Cow' - ] - end - - # Builds the object - # @param [Mixed] Data to be matched against the list of oneOf items - # @return [Object] Returns the model or the data itself - def build(data) - # Go through the list of oneOf items and attempt to identify the appropriate one. - # Note: - # - We do not attempt to check whether exactly one item matches. - # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 }) - # due to the way the deserialization is made in the base_object template (it just casts without verifying). - # - TODO: scalar values are de facto behaving as if they were nullable. - # - TODO: logging when debugging is set. - openapi_one_of.each do |klass| - begin - next if klass == :AnyType # "nullable: true" - typed_data = find_and_cast_into_type(klass, data) - return typed_data if typed_data - rescue # rescue all errors so we keep iterating even if the current item lookup raises - end - end - - openapi_one_of.include?(:AnyType) ? data : nil - end - - private - - SchemaMismatchError = Class.new(StandardError) - - # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse. - def find_and_cast_into_type(klass, data) - return if data.nil? - - case klass.to_s - when 'Boolean' - return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass) - when 'Float' - return data if data.instance_of?(Float) - when 'Integer' - return data if data.instance_of?(Integer) - when 'Time' - return Time.parse(data) - when 'Date' - return Date.parse(data) - when 'String' - return data if data.instance_of?(String) - when 'Object' # "type: object" - return data if data.instance_of?(Hash) - when /\AArray<(?.+)>\z/ # "type: array" - if data.instance_of?(Array) - sub_type = Regexp.last_match[:sub_type] - return data.map { |item| find_and_cast_into_type(sub_type, item) } - end - when /\AHash.+)>\z/ # "type: object" with "additionalProperties: { ... }" - if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) } - sub_type = Regexp.last_match[:sub_type] - return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) } - end - else # model - const = Petstore.const_get(klass) - if const - if const.respond_to?(:openapi_one_of) # nested oneOf model - model = const.build(data) - return model if model - else - # raise if data contains keys that are not known to the model - raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty? - model = const.build_from_hash(data) - return model if model - end - end - end - - raise # if no match by now, raise - rescue - raise SchemaMismatchError, "#{data} doesn't match the #{klass} type" - end - end - end - -end diff --git a/samples/client/petstore/ruby-httpx/spec/models/mamal_with_enum_spec.rb b/samples/client/petstore/ruby-httpx/spec/models/mamal_with_enum_spec.rb deleted file mode 100644 index 5622e5ed8622..000000000000 --- a/samples/client/petstore/ruby-httpx/spec/models/mamal_with_enum_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -=begin -#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 - -Generated by: https://openapi-generator.tech -Generator version: 7.11.0-SNAPSHOT - -=end - -require 'spec_helper' -require 'json' -require 'date' - -# Unit tests for Petstore::MamalWithEnum -# Automatically generated by openapi-generator (https://openapi-generator.tech) -# Please update as you see appropriate -describe Petstore::MamalWithEnum do - describe '.openapi_one_of' do - it 'lists the items referenced in the oneOf array' do - expect(described_class.openapi_one_of).to_not be_empty - end - end - - describe '.build' do - it 'returns the correct model' do - # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/ - end - end -end diff --git a/samples/client/petstore/ruby/.openapi-generator/FILES b/samples/client/petstore/ruby/.openapi-generator/FILES index 937697a733e7..7bc5bf3b003e 100644 --- a/samples/client/petstore/ruby/.openapi-generator/FILES +++ b/samples/client/petstore/ruby/.openapi-generator/FILES @@ -37,7 +37,6 @@ docs/FormatTest.md docs/HasOnlyReadOnly.md docs/HealthCheckResult.md docs/List.md -docs/MamalWithEnum.md docs/Mammal.md docs/MammalAnyof.md docs/MammalWithoutDiscriminator.md @@ -108,7 +107,6 @@ lib/petstore/models/format_test.rb lib/petstore/models/has_only_read_only.rb lib/petstore/models/health_check_result.rb lib/petstore/models/list.rb -lib/petstore/models/mamal_with_enum.rb lib/petstore/models/mammal.rb lib/petstore/models/mammal_anyof.rb lib/petstore/models/mammal_without_discriminator.rb diff --git a/samples/client/petstore/ruby/README.md b/samples/client/petstore/ruby/README.md index 443714e17c78..51fdbd87c377 100644 --- a/samples/client/petstore/ruby/README.md +++ b/samples/client/petstore/ruby/README.md @@ -153,7 +153,6 @@ Class | Method | HTTP request | Description - [Petstore::HasOnlyReadOnly](docs/HasOnlyReadOnly.md) - [Petstore::HealthCheckResult](docs/HealthCheckResult.md) - [Petstore::List](docs/List.md) - - [Petstore::MamalWithEnum](docs/MamalWithEnum.md) - [Petstore::Mammal](docs/Mammal.md) - [Petstore::MammalAnyof](docs/MammalAnyof.md) - [Petstore::MammalWithoutDiscriminator](docs/MammalWithoutDiscriminator.md) diff --git a/samples/client/petstore/ruby/docs/MamalWithEnum.md b/samples/client/petstore/ruby/docs/MamalWithEnum.md deleted file mode 100644 index 37b9252a2c82..000000000000 --- a/samples/client/petstore/ruby/docs/MamalWithEnum.md +++ /dev/null @@ -1,47 +0,0 @@ -# Petstore::MamalWithEnum - -## Class instance methods - -### `openapi_one_of` - -Returns the list of classes defined in oneOf. - -#### Example - -```ruby -require 'petstore' - -Petstore::MamalWithEnum.openapi_one_of -# => -# [ -# :'Cow' -# ] -``` - -### build - -Find the appropriate object from the `openapi_one_of` list and casts the data into it. - -#### Example - -```ruby -require 'petstore' - -Petstore::MamalWithEnum.build(data) -# => # - -Petstore::MamalWithEnum.build(data_that_doesnt_match) -# => nil -``` - -#### Parameters - -| Name | Type | Description | -| ---- | ---- | ----------- | -| **data** | **Mixed** | data to be matched against the list of oneOf items | - -#### Return type - -- `Cow` -- `nil` (if no type matches) - diff --git a/samples/client/petstore/ruby/lib/petstore.rb b/samples/client/petstore/ruby/lib/petstore.rb index 9dd6adc78a2b..96ae84db16ae 100644 --- a/samples/client/petstore/ruby/lib/petstore.rb +++ b/samples/client/petstore/ruby/lib/petstore.rb @@ -42,7 +42,6 @@ require 'petstore/models/has_only_read_only' require 'petstore/models/health_check_result' require 'petstore/models/list' -require 'petstore/models/mamal_with_enum' require 'petstore/models/mammal' require 'petstore/models/mammal_anyof' require 'petstore/models/mammal_without_discriminator' diff --git a/samples/client/petstore/ruby/lib/petstore/models/mamal_with_enum.rb b/samples/client/petstore/ruby/lib/petstore/models/mamal_with_enum.rb deleted file mode 100644 index efe0f135afee..000000000000 --- a/samples/client/petstore/ruby/lib/petstore/models/mamal_with_enum.rb +++ /dev/null @@ -1,104 +0,0 @@ -=begin -#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 - -Generated by: https://openapi-generator.tech -Generator version: 7.13.0-SNAPSHOT - -=end - -require 'date' -require 'time' - -module Petstore - module MamalWithEnum - class << self - # List of class defined in oneOf (OpenAPI v3) - def openapi_one_of - [ - :'Cow' - ] - end - - # Builds the object - # @param [Mixed] Data to be matched against the list of oneOf items - # @return [Object] Returns the model or the data itself - def build(data) - # Go through the list of oneOf items and attempt to identify the appropriate one. - # Note: - # - We do not attempt to check whether exactly one item matches. - # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 }) - # due to the way the deserialization is made in the base_object template (it just casts without verifying). - # - TODO: scalar values are de facto behaving as if they were nullable. - # - TODO: logging when debugging is set. - openapi_one_of.each do |klass| - begin - next if klass == :AnyType # "nullable: true" - typed_data = find_and_cast_into_type(klass, data) - return typed_data if typed_data - rescue # rescue all errors so we keep iterating even if the current item lookup raises - end - end - - openapi_one_of.include?(:AnyType) ? data : nil - end - - private - - SchemaMismatchError = Class.new(StandardError) - - # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse. - def find_and_cast_into_type(klass, data) - return if data.nil? - - case klass.to_s - when 'Boolean' - return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass) - when 'Float' - return data if data.instance_of?(Float) - when 'Integer' - return data if data.instance_of?(Integer) - when 'Time' - return Time.parse(data) - when 'Date' - return Date.parse(data) - when 'String' - return data if data.instance_of?(String) - when 'Object' # "type: object" - return data if data.instance_of?(Hash) - when /\AArray<(?.+)>\z/ # "type: array" - if data.instance_of?(Array) - sub_type = Regexp.last_match[:sub_type] - return data.map { |item| find_and_cast_into_type(sub_type, item) } - end - when /\AHash.+)>\z/ # "type: object" with "additionalProperties: { ... }" - if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) } - sub_type = Regexp.last_match[:sub_type] - return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) } - end - else # model - const = Petstore.const_get(klass) - if const - if const.respond_to?(:openapi_one_of) # nested oneOf model - model = const.build(data) - return model if model - else - # raise if data contains keys that are not known to the model - raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty? - model = const.build_from_hash(data) - return model if model - end - end - end - - raise # if no match by now, raise - rescue - raise SchemaMismatchError, "#{data} doesn't match the #{klass} type" - end - end - end - -end diff --git a/samples/client/petstore/ruby/spec/models/mamal_with_enum_spec.rb b/samples/client/petstore/ruby/spec/models/mamal_with_enum_spec.rb deleted file mode 100644 index e3c1f1255c1a..000000000000 --- a/samples/client/petstore/ruby/spec/models/mamal_with_enum_spec.rb +++ /dev/null @@ -1,36 +0,0 @@ -=begin -#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 - -Generated by: https://openapi-generator.tech -OpenAPI Generator version: 7.3.0-SNAPSHOT - -=end - -require 'spec_helper' -require 'json' -require 'date' - -# Unit tests for Petstore::MamalWithEnum -# Automatically generated by openapi-generator (https://openapi-generator.tech) -# Please update as you see appropriate -describe Petstore::MamalWithEnum do - describe '.openapi_one_of' do - it 'lists the items referenced in the oneOf array' do - expect(described_class.openapi_one_of).to_not be_empty - end - end - - describe '.build' do - it 'returns the correct model' do - expect(described_class.build("BlackAndWhiteCow")).to eq(Petstore::Cow::BLACK_AND_WHITE_COW) - end - - it 'returns nil for unknown model' do - expect(described_class.build({ classname: 'monkey', type: 'gorilla' })).to be_nil - end - end -end