diff --git a/lib/dry/schema/extensions/json_schema/schema_compiler.rb b/lib/dry/schema/extensions/json_schema/schema_compiler.rb index 663feb25..f4383693 100644 --- a/lib/dry/schema/extensions/json_schema/schema_compiler.rb +++ b/lib/dry/schema/extensions/json_schema/schema_compiler.rb @@ -97,7 +97,7 @@ def visit_set(node, opts = EMPTY_HASH) target_info = opts[:member] ? {items: target.to_h} : target.to_h type = opts[:member] ? "array" : "object" - keys.update(key => {**keys[key], type: type, **target_info}) + merge_opts!(keys[key], {type: type, **target_info}) end # @api private @@ -210,7 +210,7 @@ def merge_opts!(orig_opts, new_opts) orig_type = orig_opts[:type] if orig_type && new_type && orig_type != new_type - new_opts[:type] = [orig_type, new_type] + new_opts[:type] = [orig_type, new_type].flatten.uniq end orig_opts.merge!(new_opts) diff --git a/spec/extensions/json_schema/schema_spec.rb b/spec/extensions/json_schema/schema_spec.rb index c766aba6..0ca711b4 100644 --- a/spec/extensions/json_schema/schema_spec.rb +++ b/spec/extensions/json_schema/schema_spec.rb @@ -122,6 +122,68 @@ end end + context "when using maybe array types" do + include_examples "metaschema validation" + + subject(:schema) do + Dry::Schema.JSON do + required(:list).maybe(:array).each(:str?) + end + end + + it "returns the correct json schema" do + expect(schema.json_schema).to eql( + "$schema": "http://json-schema.org/draft-06/schema#", + type: "object", + properties: { + list: { + type: %w[null array], + items: { + type: "string" + } + } + }, + required: %w[list] + ) + end + end + + context "when using maybe array types with nested properties" do + include_examples "metaschema validation" + + subject(:schema) do + Dry::Schema.JSON do + required(:list).maybe(:array).each do + hash do + required(:name).value(:string) + end + end + end + end + + it "returns the correct json schema" do + expect(schema.json_schema).to eql( + "$schema": "http://json-schema.org/draft-06/schema#", + type: "object", + properties: { + list: { + type: %w[null array], + items: { + type: "object", + properties: { + name: { + type: "string" + } + }, + required: %w[name] + } + } + }, + required: %w[list] + ) + end + end + describe "filled macro" do context "when there is no type" do include_examples "metaschema validation"