diff --git a/sample/Demo.ApiDesign/SingleFileVersion/Api.v1.yaml b/sample/Demo.ApiDesign/SingleFileVersion/Api.v1.yaml index 8f289446..ba8208f8 100644 --- a/sample/Demo.ApiDesign/SingleFileVersion/Api.v1.yaml +++ b/sample/Demo.ApiDesign/SingleFileVersion/Api.v1.yaml @@ -779,12 +779,31 @@ components: nullable: true oneOf: - $ref: '#/components/schemas/Address' + tags: + type: object + additionalProperties: + type: string + desiredProperties1: + type: object + additionalProperties: + type: string + desiredProperties2: + type: object + nullable: true + additionalProperties: + type: string + desiredProperties3: + type: object + nullable: true + additionalProperties: + type: integer required: - firstName - lastName - myDateTime - email - gender + - tags CreateUsersRequest: description: A list of users. type: array diff --git a/sample/src/Demo.Api.Generated/Contracts/Users/Models/CreateUserRequest.cs b/sample/src/Demo.Api.Generated/Contracts/Users/Models/CreateUserRequest.cs index 3f76522e..9e7e4cf4 100644 --- a/sample/src/Demo.Api.Generated/Contracts/Users/Models/CreateUserRequest.cs +++ b/sample/src/Demo.Api.Generated/Contracts/Users/Models/CreateUserRequest.cs @@ -1,5 +1,5 @@ //------------------------------------------------------------------------------ -// This code was auto-generated by ApiGenerator 2.0.265.35674. +// This code was auto-generated by ApiGenerator 2.0.413.49179. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -9,7 +9,7 @@ namespace Demo.Api.Generated.Contracts.Users; /// /// Request to create a user. /// -[GeneratedCode("ApiGenerator", "2.0.265.35674")] +[GeneratedCode("ApiGenerator", "2.0.413.49179")] public class CreateUserRequest { [Required] @@ -50,7 +50,16 @@ public class CreateUserRequest public Address? MyNullableAddress { get; set; } + [Required] + public Dictionary Tags { get; set; } + + public Dictionary DesiredProperties1 { get; set; } + + public Dictionary? DesiredProperties2 { get; set; } + + public Dictionary? DesiredProperties3 { get; set; } + /// public override string ToString() - => $"{nameof(FirstName)}: {FirstName}, {nameof(LastName)}: {LastName}, {nameof(MyNullableDateTime)}: ({MyNullableDateTime}), {nameof(MyDateTime)}: ({MyDateTime}), {nameof(Email)}: {Email}, {nameof(Homepage)}: ({Homepage}), {nameof(Gender)}: {Gender}, {nameof(MyNullableAddress)}: ({MyNullableAddress})"; + => $"{nameof(FirstName)}: {FirstName}, {nameof(LastName)}: {LastName}, {nameof(MyNullableDateTime)}: ({MyNullableDateTime}), {nameof(MyDateTime)}: ({MyDateTime}), {nameof(Email)}: {Email}, {nameof(Homepage)}: ({Homepage}), {nameof(Gender)}: {Gender}, {nameof(MyNullableAddress)}: ({MyNullableAddress}), {nameof(Tags)}: ({Tags}), {nameof(DesiredProperties1)}: ({DesiredProperties1}), {nameof(DesiredProperties2)}: ({DesiredProperties2}), {nameof(DesiredProperties3)}: ({DesiredProperties3})"; } \ No newline at end of file diff --git a/sample/src/Demo.Api.Generated/Resources/ApiSpecification.yaml b/sample/src/Demo.Api.Generated/Resources/ApiSpecification.yaml index 8f289446..ba8208f8 100644 --- a/sample/src/Demo.Api.Generated/Resources/ApiSpecification.yaml +++ b/sample/src/Demo.Api.Generated/Resources/ApiSpecification.yaml @@ -779,12 +779,31 @@ components: nullable: true oneOf: - $ref: '#/components/schemas/Address' + tags: + type: object + additionalProperties: + type: string + desiredProperties1: + type: object + additionalProperties: + type: string + desiredProperties2: + type: object + nullable: true + additionalProperties: + type: string + desiredProperties3: + type: object + nullable: true + additionalProperties: + type: integer required: - firstName - lastName - myDateTime - email - gender + - tags CreateUsersRequest: description: A list of users. type: array diff --git a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/ServerClient/ContentGeneratorServerClientModelParametersFactory.cs b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/ServerClient/ContentGeneratorServerClientModelParametersFactory.cs index d8eb993e..1e54b5ef 100644 --- a/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/ServerClient/ContentGeneratorServerClientModelParametersFactory.cs +++ b/src/Atc.Rest.ApiGenerator.Framework/Factories/Parameters/ServerClient/ContentGeneratorServerClientModelParametersFactory.cs @@ -125,6 +125,14 @@ private static List ExtractPropertiesParameters( dataType = openApiParameter.AnyOf.Count == 1 ? openApiParameter.AnyOf[0].GetDataType() : openApiParameter.GetDataType(); + + if ("Object".Equals(dataType, StringComparison.Ordinal) && + openApiParameter.AdditionalProperties is not null) + { + // A defined Object with AdditionalProperties is a Dictionary - https://swagger.io/docs/specification/data-models/dictionaries/ + var additionalPropertiesDataType = openApiParameter.AdditionalProperties.GetDataType(); + dataType = $"Dictionary"; + } } var isSimpleType = useListForDataType diff --git a/src/Atc.Rest.ApiGenerator.OpenApi/Validators/OpenApiDocumentValidator.cs b/src/Atc.Rest.ApiGenerator.OpenApi/Validators/OpenApiDocumentValidator.cs index cd975fcf..b541813a 100644 --- a/src/Atc.Rest.ApiGenerator.OpenApi/Validators/OpenApiDocumentValidator.cs +++ b/src/Atc.Rest.ApiGenerator.OpenApi/Validators/OpenApiDocumentValidator.cs @@ -355,7 +355,8 @@ private void ValidateSchemas( { case OpenApiDataTypeConstants.Object: { - if (!value.IsObjectReferenceTypeDeclared()) + if (!value.IsObjectReferenceTypeDeclared() && + value.AdditionalProperties is null) { logItems.Add(logItemFactory.Create(LogCategoryType.Error, ValidationRuleNameConstants.Schema10, $"Implicit object definition on property '{key}' in type '{schema.Reference.ReferenceV3}' is not supported.")); } diff --git a/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/DemoSampleApi.yaml b/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/DemoSampleApi.yaml index ded4c49e..cf543aff 100644 --- a/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/DemoSampleApi.yaml +++ b/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/DemoSampleApi.yaml @@ -779,12 +779,31 @@ components: nullable: true oneOf: - $ref: '#/components/schemas/Address' + tags: + type: object + additionalProperties: + type: string + desiredProperties1: + type: object + additionalProperties: + type: string + desiredProperties2: + type: object + nullable: true + additionalProperties: + type: string + desiredProperties3: + type: object + nullable: true + additionalProperties: + type: integer required: - firstName - lastName - myDateTime - email - gender + - tags CreateUsersRequest: description: A list of users. type: array diff --git a/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/VerifyClientCSharp/src/DemoSampleApi.ApiClient.Generated/Contracts/Users/RequestParameters/CreateUserRequest.verified.cs b/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/VerifyClientCSharp/src/DemoSampleApi.ApiClient.Generated/Contracts/Users/RequestParameters/CreateUserRequest.verified.cs index 99cc6c42..55d7c167 100644 --- a/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/VerifyClientCSharp/src/DemoSampleApi.ApiClient.Generated/Contracts/Users/RequestParameters/CreateUserRequest.verified.cs +++ b/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/VerifyClientCSharp/src/DemoSampleApi.ApiClient.Generated/Contracts/Users/RequestParameters/CreateUserRequest.verified.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // This code was auto-generated by ApiGenerator x.x.x.x. // // Changes to this file may cause incorrect behavior and will be lost if @@ -50,7 +50,16 @@ public class CreateUserRequest public Address? MyNullableAddress { get; set; } + [Required] + public Dictionary Tags { get; set; } + + public Dictionary DesiredProperties1 { get; set; } + + public Dictionary? DesiredProperties2 { get; set; } + + public Dictionary? DesiredProperties3 { get; set; } + /// public override string ToString() - => $"{nameof(FirstName)}: {FirstName}, {nameof(LastName)}: {LastName}, {nameof(MyNullableDateTime)}: ({MyNullableDateTime}), {nameof(MyDateTime)}: ({MyDateTime}), {nameof(Email)}: {Email}, {nameof(Homepage)}: ({Homepage}), {nameof(Gender)}: {Gender}, {nameof(MyNullableAddress)}: ({MyNullableAddress})"; + => $"{nameof(FirstName)}: {FirstName}, {nameof(LastName)}: {LastName}, {nameof(MyNullableDateTime)}: ({MyNullableDateTime}), {nameof(MyDateTime)}: ({MyDateTime}), {nameof(Email)}: {Email}, {nameof(Homepage)}: ({Homepage}), {nameof(Gender)}: {Gender}, {nameof(MyNullableAddress)}: ({MyNullableAddress}), {nameof(Tags)}: ({Tags}), {nameof(DesiredProperties1)}: ({DesiredProperties1}), {nameof(DesiredProperties2)}: ({DesiredProperties2}), {nameof(DesiredProperties3)}: ({DesiredProperties3})"; } \ No newline at end of file diff --git a/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/VerifyServerAll/src/DemoSampleApi.Api.Generated/Contracts/Users/Models/CreateUserRequest.verified.cs b/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/VerifyServerAll/src/DemoSampleApi.Api.Generated/Contracts/Users/Models/CreateUserRequest.verified.cs index 0cbcd944..b2a29703 100644 --- a/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/VerifyServerAll/src/DemoSampleApi.Api.Generated/Contracts/Users/Models/CreateUserRequest.verified.cs +++ b/test/Atc.Rest.ApiGenerator.CLI.Tests/DemoSampleApi/VerifyServerAll/src/DemoSampleApi.Api.Generated/Contracts/Users/Models/CreateUserRequest.verified.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // This code was auto-generated by ApiGenerator x.x.x.x. // // Changes to this file may cause incorrect behavior and will be lost if @@ -50,7 +50,16 @@ public class CreateUserRequest public Address? MyNullableAddress { get; set; } + [Required] + public Dictionary Tags { get; set; } + + public Dictionary DesiredProperties1 { get; set; } + + public Dictionary? DesiredProperties2 { get; set; } + + public Dictionary? DesiredProperties3 { get; set; } + /// public override string ToString() - => $"{nameof(FirstName)}: {FirstName}, {nameof(LastName)}: {LastName}, {nameof(MyNullableDateTime)}: ({MyNullableDateTime}), {nameof(MyDateTime)}: ({MyDateTime}), {nameof(Email)}: {Email}, {nameof(Homepage)}: ({Homepage}), {nameof(Gender)}: {Gender}, {nameof(MyNullableAddress)}: ({MyNullableAddress})"; + => $"{nameof(FirstName)}: {FirstName}, {nameof(LastName)}: {LastName}, {nameof(MyNullableDateTime)}: ({MyNullableDateTime}), {nameof(MyDateTime)}: ({MyDateTime}), {nameof(Email)}: {Email}, {nameof(Homepage)}: ({Homepage}), {nameof(Gender)}: {Gender}, {nameof(MyNullableAddress)}: ({MyNullableAddress}), {nameof(Tags)}: ({Tags}), {nameof(DesiredProperties1)}: ({DesiredProperties1}), {nameof(DesiredProperties2)}: ({DesiredProperties2}), {nameof(DesiredProperties3)}: ({DesiredProperties3})"; } \ No newline at end of file