Skip to content

Add support for additional_properties#92

Open
olivier-thatch wants to merge 1 commit into
ruby-grape:masterfrom
olivier-thatch:olivier/additional-properties
Open

Add support for additional_properties#92
olivier-thatch wants to merge 1 commit into
ruby-grape:masterfrom
olivier-thatch:olivier/additional-properties

Conversation

@olivier-thatch

Copy link
Copy Markdown
Contributor

Add support for additional_properties, similar to what already exists for params in grape-swagger (cf. docs).

Code is from Claude. I reviewed it, it looks sane to me.

Closes #83.

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

Danger Report

Errors

  • One of the lines below found in CHANGELOG.md doesn't match the expected format. Please make it look like the other lines, pay attention to version numbers, periods, spaces and date formats.

Markdowns

* [#92](https://github.com/ruby-grape/grape-swagger-entity/pull/92) Add support for `additional_properties` - [@olivier-thatch](https://github.com/olivier-thatch).

View run

@olivier-thatch olivier-thatch force-pushed the olivier/additional-properties branch from 8c4669b to 53102be Compare June 10, 2026 02:18
@dblock dblock requested a review from numbata June 10, 2026 21:39
@olivier-thatch olivier-thatch changed the title Add support for additional_properties Add support for additional_properties Jul 8, 2026
@olivier-thatch olivier-thatch force-pushed the olivier/additional-properties branch from 53102be to 1b86322 Compare July 8, 2026 21:08
type
end

def parse_additional_properties(value)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, we should route additional_properties values through the same primitive type mapping as regular documented attributes before emitting the schema.

The current implementation handles String, but formatted primitives can currently emit invalid Swagger types. For example:

additional_properties: Float

can become:

{ additionalProperties: { type: 'float' } }

but should be:

{ additionalProperties: { type: 'number', format: 'float' } }

Same idea for Date, DateTime, Time, BigDecimal, Integer, etc. One possible direction:

# Here untested pseudo-code that looks like a ruby

def document_data_type(documentation, data_type)
  type = primitive_data_type_schema(data_type) || { type: data_type }

  type[:format] = documentation[:format] if documentation.key?(:format)

  values = documentation[:values]
  values = values.call if values.is_a?(Proc)
  type[:enum] = values if values.is_a?(Array)

  if documentation.key?(:additional_properties)
    additional_properties = parse_additional_properties(documentation[:additional_properties])
    type[:additionalProperties] = additional_properties unless additional_properties.nil?
  end

  type
end

def parse_additional_properties(value)
  case value
  when String, Symbol
    if direct_model_type?(value)
      name = GrapeSwagger::Entity::Helper.model_name(value, endpoint)
      { '$ref' => "#/definitions/#{name}" }
    else
      data_type = GrapeSwagger::DocMethods::DataType.call(value.to_s)
      primitive_data_type_schema(data_type) || { type: data_type }
    end
  when Class
    data_type = GrapeSwagger::DocMethods::DataType.call(value)

    if (schema = primitive_data_type_schema(data_type))
      schema
    elsif value <= Grape::Entity
      name = GrapeSwagger::Entity::Helper.model_name(value, endpoint)
      { '$ref' => "#/definitions/#{name}" }
    else
      { type: data_type }
    end
  when true, false, Hash
    value
  end
end

def primitive_data_type_schema(data_type)
  return unless GrapeSwagger::DocMethods::DataType.primitive?(data_type)

  type, format = GrapeSwagger::DocMethods::DataType.mapping(data_type)
  { type: type }.tap { |schema| schema[:format] = format if format }
end

This would also avoid treating any non-primitive class as an entity, which can make PORO classes go through the entity parser path and fail.

Could we add specs for Float, Date, DateTime, string aliases like 'Boolean' / 'Hash', symbol aliases like :string, an entity class, and a non-entity PORO class?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support additionalProperties

2 participants