Skip to content

Commit

Permalink
Move additionalProperties to 3.0 Schema node
Browse files Browse the repository at this point in the history
This will be modelled differently for OpenAPI 3.1 where a JSON schema
can itself have a boolean value and thus we won't be using Boolean or
Schema anymore as a 3.1 Schema will suffice.
  • Loading branch information
kevindew committed Jan 30, 2025
1 parent 8a52e58 commit 07dabbf
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 62 deletions.
13 changes: 0 additions & 13 deletions lib/openapi3_parser/node/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -157,19 +157,6 @@ def properties
self["properties"]
end

# @return [Boolean]
def additional_properties?
self["additionalProperties"] != false
end

# @return [Schema, nil]
def additional_properties_schema
properties = self["additionalProperties"]
return if [true, false].include?(properties)

properties
end

# @return [String, nil]
def description
self["description"]
Expand Down
13 changes: 13 additions & 0 deletions lib/openapi3_parser/node/schema/v3_0.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,19 @@ def exclusive_maximum?
def exclusive_minimum?
self["exclusiveMinimum"]
end

# @return [Boolean]
def additional_properties?
self["additionalProperties"] != false
end

# @return [Schema, nil]
def additional_properties_schema
properties = self["additionalProperties"]
return if [true, false].include?(properties)

properties
end
end
end
end
Expand Down
17 changes: 0 additions & 17 deletions lib/openapi3_parser/node_factory/schema/common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ def self.included(base)
base.field "not", factory: :referenceable_schema
base.field "items", factory: :referenceable_schema
base.field "properties", factory: :schema_map_factory
base.field "additionalProperties",
validate: :additional_properties_input_type,
factory: :additional_properties_factory,
default: false
base.field "description", input_type: String
base.field "format", input_type: String
base.field "default"
Expand Down Expand Up @@ -106,19 +102,6 @@ def referenceable_schema_array(context)
value_factory: NodeFactory::Schema.factory(context)
)
end

def additional_properties_input_type(validatable)
input = validatable.input
return if [true, false].include?(input) || input.is_a?(Hash)

validatable.add_error("Expected a Boolean or an Object")
end

def additional_properties_factory(context)
return context.input if [true, false].include?(context.input)

referenceable_schema(context)
end
end
end
end
Expand Down
21 changes: 20 additions & 1 deletion lib/openapi3_parser/node_factory/schema/v3_0.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@ class V3_0 < NodeFactory::Object # rubocop:disable Naming/ClassAndModuleCamelCas
field "type", input_type: String

# JSON Schema 2016 has these exclusive fields as booleans whereas
# in JSON Schema 2021 (OpenAPI 3.1) these are numbers
# in JSON Schema 2020 (OpenAPI 3.1) these are numbers
field "exclusiveMaximum", input_type: :boolean, default: false
field "exclusiveMinimum", input_type: :boolean, default: false

# JSON Schema 2020 accepts a schema (albeit a more complex one) than
# this schema or boolean approach
field "additionalProperties", validate: :additional_properties_input_type,
factory: :additional_properties_factory,
default: false

validate :items_for_array

def build_node(data, node_context)
Expand All @@ -36,6 +42,19 @@ def items_for_array(validatable)

validatable.add_error("items must be defined for a type of array")
end

def additional_properties_input_type(validatable)
input = validatable.input
return if [true, false].include?(input) || input.is_a?(Hash)

validatable.add_error("Expected a Boolean or an Object")
end

def additional_properties_factory(context)
return context.input if [true, false].include?(context.input)

referenceable_schema(context)
end
end
end
end
Expand Down
31 changes: 31 additions & 0 deletions spec/lib/openapi3_parser/node_factory/schema/v3_0_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,35 @@
.with_message("items must be defined for a type of array")
end
end

describe "validating additionalProperties" do
it "is valid for a boolean" do
true_instance = described_class.new(
create_node_factory_context({ "additionalProperties" => true })
)
expect(true_instance).to be_valid

false_instance = described_class.new(
create_node_factory_context({ "additionalProperties" => false })
)
expect(false_instance).to be_valid
end

it "is valid for a schema" do
instance = described_class.new(
create_node_factory_context({ "additionalProperties" => { "type" => "object" } })
)
expect(instance).to be_valid
end

it "is invalid for something different" do
instance = described_class.new(
create_node_factory_context({ "additionalProperties" => %w[item1 item2] })
)
expect(instance).not_to be_valid
expect(instance)
.to have_validation_error("#/additionalProperties")
.with_message("Expected a Boolean or an Object")
end
end
end
31 changes: 0 additions & 31 deletions spec/support/schema_common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,37 +88,6 @@
expect(read_only).to be_valid
end
end

describe "validating additionalProperties" do
it "is valid for a boolean" do
true_instance = described_class.new(
create_node_factory_context({ "additionalProperties" => true })
)
expect(true_instance).to be_valid

false_instance = described_class.new(
create_node_factory_context({ "additionalProperties" => false })
)
expect(false_instance).to be_valid
end

it "is valid for a schema" do
instance = described_class.new(
create_node_factory_context({ "additionalProperties" => { "type" => "object" } })
)
expect(instance).to be_valid
end

it "is invalid for something different" do
instance = described_class.new(
create_node_factory_context({ "additionalProperties" => %w[item1 item2] })
)
expect(instance).not_to be_valid
expect(instance)
.to have_validation_error("#/additionalProperties")
.with_message("Expected a Boolean or an Object")
end
end
end

RSpec.shared_examples "schema node" do |openapi_version:|
Expand Down

0 comments on commit 07dabbf

Please sign in to comment.