diff --git a/CHANGELOG.md b/CHANGELOG.md index aa559f7e..08c30053 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * [#953](https://github.com/ruby-grape/grape-swagger/pull/953): Added `super_diff` - [@numbata](https://github.com/numbata). * [#951](https://github.com/ruby-grape/grape-swagger/pull/951): Use `x-example` for non-body parameters - [@olivier-thatch](https://github.com/olivier-thatch). * [#963](https://github.com/ruby-grape/grape-swagger/pull/963): Allow empty model definitions for swagger 2.0 - [@numbata](https://github.com/numbata). +* [#964](https://github.com/ruby-grape/grape-swagger/pull/964): Add support for array of primitive data types in responses - [@khiav223577](https://github.com/khiav223577). * Your contribution here. #### Fixes diff --git a/lib/grape-swagger/endpoint.rb b/lib/grape-swagger/endpoint.rb index 54dd8191..990d4fa1 100644 --- a/lib/grape-swagger/endpoint.rb +++ b/lib/grape-swagger/endpoint.rb @@ -311,16 +311,32 @@ def build_memo_schema(memo, route, value, response_model, options) end def build_response_for_type_parameter(memo, _route, value, _options) - type, format = prepare_type_and_format(value) + schema = build_response_schema(value) if memo[value[:code]].include?(:schema) && value.include?(:as) - memo[value[:code]][:schema][:properties].merge!(value[:as] => { type: type, format: format }.compact) + memo[value[:code]][:schema][:properties].merge!(schema) elsif value.include?(:as) - memo[value[:code]][:schema] = - { type: :object, properties: { value[:as] => { type: type, format: format }.compact } } + memo[value[:code]][:schema] = { type: :object, properties: schema } else - memo[value[:code]][:schema] = { type: type } + memo[value[:code]][:schema] = schema + end + end + + def build_response_schema(value) + return { value[:as] => build_response_schema(value.except(:as)) } if value.include?(:as) + + if value[:type].is_a?(Array) + items = if value[:type].size == 1 + build_response_schema({ **value, type: value[:type].first }) + else + { oneOf: value[:type].map { |type| build_response_schema({ **value, type: type }) } } + end + + return { type: 'array', items: items } end + + type, format = prepare_type_and_format(value) + { type: type, format: format }.compact end def prepare_type_and_format(value) diff --git a/spec/swagger_v2/api_swagger_v2_response_with_models_and_primitive_types_spec.rb b/spec/swagger_v2/api_swagger_v2_response_with_models_and_primitive_types_spec.rb index 8050f1b6..76979f90 100644 --- a/spec/swagger_v2/api_swagger_v2_response_with_models_and_primitive_types_spec.rb +++ b/spec/swagger_v2/api_swagger_v2_response_with_models_and_primitive_types_spec.rb @@ -16,7 +16,13 @@ class ResponseApiModelsAndPrimitiveTypes < Grape::API { model: Entities::UseResponse, as: :user_response }, { type: 'String', as: :string_response }, { type: 'Float', as: :float_response }, - { type: 'Hash', as: :hash_response } + { type: 'Hash', as: :hash_response }, + { type: Array[Integer], as: :array_of_integer_response }, + { type: Array[String], as: :array_of_string_response }, + { type: Array[Float], as: :array_of_float_response }, + { type: Array[Hash], as: :array_of_hash_response }, + { type: Array[Array[Float]], as: :array_of_array_of_float_response }, + { type: Array[Integer, String], as: :array_of_integer_or_string_response } ], failure: [ { code: 400, message: 'NotFound', model: '' }, @@ -56,7 +62,52 @@ def app 'integer_response' => { 'type' => 'integer', 'format' => 'int32' }, 'string_response' => { 'type' => 'string' }, 'float_response' => { 'type' => 'number', 'format' => 'float' }, - 'hash_response' => { 'type' => 'object' } + 'hash_response' => { 'type' => 'object' }, + 'array_of_integer_response' => { + 'type' => 'array', + 'items' => { + 'type' => 'integer', + 'format' => 'int32' + } + }, + 'array_of_string_response' => { + 'type' => 'array', + 'items' => { + 'type' => 'string' + } + }, + 'array_of_float_response' => { + 'type' => 'array', + 'items' => { + 'type' => 'number', + 'format' => 'float' + } + }, + 'array_of_hash_response' => { + 'type' => 'array', + 'items' => { + 'type' => 'object' + } + }, + 'array_of_array_of_float_response' => { + 'type' => 'array', + 'items' => { + 'type' => 'array', + 'items' => { + 'type' => 'number', + 'format' => 'float' + } + } + }, + 'array_of_integer_or_string_response' => { + 'type' => 'array', + 'items' => { + 'oneOf' => [ + { 'type' => 'integer', 'format' => 'int32' }, + { 'type' => 'string' } + ] + } + } } } },