Class: Jimmy::Schema
- Inherits:
-
Json::Hash
- Object
- Json::Hash
- Jimmy::Schema
- Includes:
- Declaration
- Defined in:
- lib/jimmy/schema.rb,
lib/jimmy/schema/json.rb,
lib/jimmy/schema/array.rb,
lib/jimmy/schema/number.rb,
lib/jimmy/schema/object.rb,
lib/jimmy/schema/string.rb,
lib/jimmy/schema/casting.rb,
lib/jimmy/schema/operators.rb,
lib/jimmy/schema/conditions.rb
Overview
Represents a schema as defined by json-schema.org/draft-07/schema
Constant Summary collapse
- PROPERTIES =
%w[ title description default readOnly writeOnly examples multipleOf maximum exclusiveMaximum minimum exclusiveMinimum maxLength minLength pattern additionalItems items maxItems minItems uniqueItems contains maxProperties minProperties required additionalProperties definitions properties patternProperties dependencies propertyNames const enum type format contentMediaType contentEncoding if then else allOf anyOf oneOf not ].freeze
- PROPERTY_SEQUENCE =
PROPERTIES.each.with_index.to_h.freeze
- SCHEMA =
The JSON Schema draft 7 schema URI
'http://json-schema.org/draft-07/schema#'
Constants included from Declaration
Declaration::BOOLEANS, Declaration::FORMATS, Declaration::SIMPLE_TYPES
Instance Method Summary collapse
-
#==(other) ⇒ true, false
Compare the schema to another schema.
-
#[]=(key, value) ⇒ Object
Set a property of the schema.
-
#additional_properties(schema) ⇒ self
Set the schema for additional properties not matching those given to
#require
,#property
, and#properties
. -
#and(other) ⇒ Jimmy::Schema
(also: #&)
Combine this schema with another schema using an
allOf
schema. -
#anything? ⇒ true, false
Returns true when the schema will validate against anything.
-
#as_json(id: '', index: nil) ⇒ Hash, ...
Get the schema as a plain Hash.
-
#count(range) ⇒ self
Set the minimum and maximum items for an array value, using a range.
-
#deep_dup ⇒ Jimmy::Json::Schema
Duplicate the schema.
-
#dup ⇒ Jimmy::Json::Schema
Duplicate the schema with a shallow copy.
-
#else(schema) ⇒ self
Define the schema that must be valid if the
if
schema is not valid. -
#exclusive_maximum(number) ⇒ self
Set the exclusive maximum value.
-
#exclusive_minimum(number) ⇒ self
Set the exclusive minimum value.
-
#format(format_name) ⇒ self
Set the format for a string value.
-
#initialize(schema = {}) {|schema| ... } ⇒ Schema
constructor
A new instance of Schema.
- #inspect ⇒ Object
-
#item(*single_item_schemas) ⇒ self
Add a single-item schema, or several, to the
items
array. -
#items(schema_or_schemas, rest_schema = nil) ⇒ self
Set the schema or schemas for validating items in an array value.
-
#length(range) ⇒ self
Set the minimum and maximum length for a string value, using a range.
-
#max_items(count) ⇒ self
Set the maximum items for an array value.
-
#max_length(length) ⇒ self
Set the maximum length for a string value.
-
#maximum(number, exclusive: false) ⇒ self
Set the maximum value.
-
#min_items(count) ⇒ self
Set the minimum items for an array value.
-
#min_length(length) ⇒ self
Set the minimum length for a string value.
-
#minimum(number, exclusive: false) ⇒ self
Set the minimum value.
-
#negated ⇒ Jimmy::Schema
(also: #!)
Get the opposite of this schema, by wrapping it in a new schema’s
not
property. -
#nothing ⇒ self
Make the schema validate nothing (i.e. everything is invalid).
-
#nothing? ⇒ true, false
Returns true when the schema will never validate against anything.
-
#or(other) ⇒ Jimmy::Schema
(also: #|)
Combine this schema with another schema using an
anyOf
schema. -
#properties(properties, required: false) {|name, schema| ... } ⇒ self
(also: #allow)
Define properties for an object value.
-
#property(name, schema = Schema.new, required: false) {|schema| ... } ⇒ self
Define a property for an object value.
-
#ref(uri) ⇒ self
Turns the schema into a reference to another schema.
-
#ref? ⇒ true, false
Returns true if the schema refers to another schema.
-
#require(*properties) {|name, schema| ... } ⇒ self
(also: #requires)
Designate the given properties as required for object values.
-
#require_all ⇒ self
Require all properties that have been explicitly defined for object values.
- #sort_keys_by(key, _value) ⇒ Object private
-
#target ⇒ Json::URI?
Get the URI of the schema to which this schema refers, or nil if the schema is not a reference.
-
#then(schema) ⇒ self
Define the schema that must be valid if the
if
schema is valid. -
#unique_items(unique = true) ⇒ self
(also: #unique)
Set whether the array value is required to have unique items.
-
#xor(other) ⇒ Jimmy::Schema
(also: #^)
Combine this schema with another schema using a
oneOf
schema.
Methods included from Declaration
#all_of, #any_of, #array, #boolean, #const, #date, #date_time, #default, #define, #definitions, #description, #email, #enum, #examples, #hostname, #idn_email, #idn_hostname, #if, #integer, #ipv4, #ipv6, #iri, #iri_reference, #json_pointer, #multiple_of, #not, #null, #number, #object, #one_of, #pattern, #range, #read_only, #regex, #relative_json_pointer, #string, #struct, #time, #title, #type, #uri, #uri_reference, #uri_template, #write_only
Methods inherited from Json::Hash
#each, #fetch, #get_fragment, #key?, #keys, #merge!
Methods included from Json::Collection
#[], #clear, #dig, #empty?, #freeze, #to_json
Constructor Details
#initialize(schema = {}) {|schema| ... } ⇒ Schema
Returns a new instance of Schema.
28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/jimmy/schema.rb', line 28 def initialize(schema = {}) @nothing = false case schema when *CASTABLE_CLASSES super({}) apply_cast self, schema when Hash then super else raise Error::WrongType, "Unexpected #{schema.class}" end yield self if block_given? end |
Instance Method Details
#==(other) ⇒ true, false
Compare the schema to another schema.
8 9 10 11 12 |
# File 'lib/jimmy/schema/operators.rb', line 8 def ==(other) return false unless other.is_a? Schema other.as_json == as_json end |
#[]=(key, value) ⇒ Object
Set a property of the schema.
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/jimmy/schema.rb', line 55 def []=(key, value) @nothing = false case key when '$id' then @id = value # TODO: something, with this when '$ref' then ref value when '$schema' URI(value) == URI(SCHEMA) or raise Error::BadArgument, 'Unsupported JSON schema draft' when '$comment' then @comment = value # TODO: something, with this else super end end |
#additional_properties(schema) ⇒ self
Set the schema for additional properties not matching those given to #require
, #property
, and #properties
. Pass false
to disallow additional properties.
83 84 85 |
# File 'lib/jimmy/schema/object.rb', line 83 def additional_properties(schema) set additionalProperties: cast_schema(schema) end |
#and(other) ⇒ Jimmy::Schema Also known as: &
Combine this schema with another schema using an allOf
schema. If this schema’s only property is allOf
, its items will be flattened into the new schema.
Since #& is an alias of #and
, the following two statements are equivalent:
schema.and(other)
schema & other
48 49 50 |
# File 'lib/jimmy/schema/operators.rb', line 48 def and(other) make_new_composite 'allOf', other end |
#anything? ⇒ true, false
Returns true when the schema will validate against anything.
48 49 50 |
# File 'lib/jimmy/schema.rb', line 48 def anything? !@nothing && empty? end |
#as_json(id: '', index: nil) ⇒ Hash, ...
Get the schema as a plain Hash. Given an id
, the $id and $schema keys will also be set.
12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/jimmy/schema/json.rb', line 12 def as_json(id: '', index: nil) id = Json::URI.new(id) if index.nil? && id.absolute? return top_level_json(id) { super index: {}, id: id } end return true if anything? return false if nothing? super index: index || {}, id: id end |
#count(range) ⇒ self
Set the minimum and maximum items for an array value, using a range.
39 40 41 42 43 44 45 |
# File 'lib/jimmy/schema/array.rb', line 39 def count(range) range = range..range if range.is_a?(Integer) assert_range range min_items range.min max_items range.max unless range.end.nil? self end |
#deep_dup ⇒ Jimmy::Json::Schema
Duplicate the schema.
127 128 129 |
# File 'lib/jimmy/schema.rb', line 127 def deep_dup(*) nothing? ? self.class.new.nothing : super end |
#dup ⇒ Jimmy::Json::Schema
Duplicate the schema with a shallow copy. Collections like properties, enum, etc, will be shared with the duplicate.
121 122 123 |
# File 'lib/jimmy/schema.rb', line 121 def dup nothing? ? self.class.new.nothing : super end |
#else(schema) ⇒ self
Define the schema that must be valid if the if
schema is not valid.
15 16 17 |
# File 'lib/jimmy/schema/conditions.rb', line 15 def else(schema) set else: cast_schema(schema) end |
#exclusive_maximum(number) ⇒ self
Set the exclusive maximum value.
33 34 35 |
# File 'lib/jimmy/schema/number.rb', line 33 def exclusive_maximum(number) maximum number, exclusive: true end |
#exclusive_minimum(number) ⇒ self
Set the exclusive minimum value.
17 18 19 |
# File 'lib/jimmy/schema/number.rb', line 17 def exclusive_minimum(number) minimum number, exclusive: true end |
#format(format_name) ⇒ self
Set the format for a string value.
38 39 40 41 42 |
# File 'lib/jimmy/schema/string.rb', line 38 def format(format_name) valid_for 'string' assert_string format_name set format: format_name end |
#inspect ⇒ Object
70 71 72 |
# File 'lib/jimmy/schema.rb', line 70 def inspect "#<#{self.class} #{super}>" end |
#item(*single_item_schemas) ⇒ self
Add a single-item schema, or several, to the items
array. Only valid if a match-all schema has not been set.
71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/jimmy/schema/array.rb', line 71 def item(*single_item_schemas) valid_for 'array' assert_array(single_item_schemas, minimum: 1) existing = getset('items') { [] } assert !existing.is_a?(Schema) do 'Cannot add individual item schemas after adding a match-all schema' end single_item_schemas.each do |schema| existing << cast_schema(schema) end self end |
#items(schema_or_schemas, rest_schema = nil) ⇒ self
Set the schema or schemas for validating items in an array value.
56 57 58 59 60 61 62 63 64 |
# File 'lib/jimmy/schema/array.rb', line 56 def items(schema_or_schemas, rest_schema = nil) if schema_or_schemas.is_a? Array item *schema_or_schemas set additionalItems: cast_schema(rest_schema) if rest_schema else match_all_items schema_or_schemas, rest_schema end self end |
#length(range) ⇒ self
Set the minimum and maximum length for a string value, using a range.
27 28 29 30 31 32 33 |
# File 'lib/jimmy/schema/string.rb', line 27 def length(range) range = range..range if range.is_a?(Integer) assert_range range min_length range.min max_length range.max unless range.end.nil? self end |
#max_items(count) ⇒ self
Set the maximum items for an array value.
20 21 22 23 24 |
# File 'lib/jimmy/schema/array.rb', line 20 def max_items(count) valid_for 'array' assert_numeric count, minimum: 0 set maxItems: count end |
#max_length(length) ⇒ self
Set the maximum length for a string value.
8 9 10 11 12 |
# File 'lib/jimmy/schema/string.rb', line 8 def max_length(length) valid_for 'string' assert_numeric length, minimum: 0 set maxLength: length end |
#maximum(number, exclusive: false) ⇒ self
Set the maximum value.
26 27 28 |
# File 'lib/jimmy/schema/number.rb', line 26 def maximum(number, exclusive: false) set_numeric_boundary 'maximum', number, exclusive end |
#min_items(count) ⇒ self
Set the minimum items for an array value.
29 30 31 32 33 |
# File 'lib/jimmy/schema/array.rb', line 29 def min_items(count) valid_for 'array' assert_numeric count, minimum: 0 set minItems: count end |
#min_length(length) ⇒ self
Set the minimum length for a string value.
17 18 19 20 21 |
# File 'lib/jimmy/schema/string.rb', line 17 def min_length(length) valid_for 'string' assert_numeric length, minimum: 0 set minLength: length end |
#minimum(number, exclusive: false) ⇒ self
Set the minimum value.
10 11 12 |
# File 'lib/jimmy/schema/number.rb', line 10 def minimum(number, exclusive: false) set_numeric_boundary 'minimum', number, exclusive end |
#negated ⇒ Jimmy::Schema Also known as: !
Get the opposite of this schema, by wrapping it in a new schema’s not
property.
If this schema’s only property is not
, its value will instead be returned. Therefore:
schema.negated.negated == schema
Since #! is an alias for #negated
, this also works:
!!schema == schema
Schemas matching absolutes ANYTHING
or NOTHING
will return the opposite absolute.
29 30 31 32 33 34 35 |
# File 'lib/jimmy/schema/operators.rb', line 29 def negated return Schema.new if nothing? return Schema.new.nothing if anything? return get('not') if keys == ['not'] Schema.new.not self end |
#nothing ⇒ self
Make the schema validate nothing (i.e. everything is invalid).
90 91 92 93 94 |
# File 'lib/jimmy/schema.rb', line 90 def nothing clear @nothing = true self end |
#nothing? ⇒ true, false
Returns true when the schema will never validate against anything.
42 43 44 |
# File 'lib/jimmy/schema.rb', line 42 def nothing? @nothing end |
#or(other) ⇒ Jimmy::Schema Also known as: |
Combine this schema with another schema using an anyOf
schema. If this schema’s only property is anyOf
, its items will be flattened into the new schema.
Since #| is an alias of #or
, the following two statements are equivalent:
schema.or(other)
schema | other
63 64 65 |
# File 'lib/jimmy/schema/operators.rb', line 63 def or(other) make_new_composite 'anyOf', other end |
#properties(properties, required: false) {|name, schema| ... } ⇒ self Also known as: allow
Define properties for an object value.
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/jimmy/schema/object.rb', line 33 def properties(properties, required: false, &block) valid_for 'object' assert_hash properties groups = properties.group_by { |k, _| collection_for_property_key k } groups.each do |collection, pairs| batch_assign_to_schema_hash collection, pairs.to_h, &block end require *properties.keys if required self end |
#property(name, schema = Schema.new, required: false) {|schema| ... } ⇒ self
Define a property for an object value.
14 15 16 17 18 19 20 21 22 |
# File 'lib/jimmy/schema/object.rb', line 14 def property(name, schema = Schema.new, required: false, &block) return properties(name, required: required, &block) if name.is_a? Hash valid_for 'object' collection = collection_for_property_key(name) assign_to_schema_hash collection, name, schema, &block require name if required self end |
#ref(uri) ⇒ self
Turns the schema into a reference to another schema. Freezes the schema so that no further changes can be made.
79 80 81 82 83 84 85 86 |
# File 'lib/jimmy/schema.rb', line 79 def ref(uri) assert empty? do 'Reference schemas cannot have other properties: ' + keys.join(', ') end @members['$ref'] = Json::URI.new(uri) freeze end |
#ref? ⇒ true, false
Returns true if the schema refers to another schema.
105 106 107 |
# File 'lib/jimmy/schema.rb', line 105 def ref? key? '$ref' end |
#require(*properties) {|name, schema| ... } ⇒ self Also known as: requires
Designate the given properties as required for object values.
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/jimmy/schema/object.rb', line 56 def require(*properties, &block) properties.each do |name| if name.is_a? Hash self.properties name, required: true, &block else arr = getset('required') { [] } name = validate_property_name(name) arr << name unless arr.include? name end end self end |
#require_all ⇒ self
Require all properties that have been explicitly defined for object
values.
74 75 76 |
# File 'lib/jimmy/schema/object.rb', line 74 def require_all require *get('properties') { {} }.keys end |
#sort_keys_by(key, _value) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
114 115 116 |
# File 'lib/jimmy/schema.rb', line 114 def sort_keys_by(key, _value) # :nodoc: PROPERTY_SEQUENCE.fetch(key) { raise KeyError, 'Not a valid schema key' } end |
#target ⇒ Json::URI?
Get the URI of the schema to which this schema refers, or nil if the schema is not a reference.
99 100 101 |
# File 'lib/jimmy/schema.rb', line 99 def target self['$ref'] end |
#then(schema) ⇒ self
Define the schema that must be valid if the if
schema is valid.
8 9 10 |
# File 'lib/jimmy/schema/conditions.rb', line 8 def then(schema) set then: cast_schema(schema) end |
#unique_items(unique = true) ⇒ self Also known as: unique
Set whether the array value is required to have unique items.
9 10 11 12 13 |
# File 'lib/jimmy/schema/array.rb', line 9 def unique_items(unique = true) valid_for 'array' assert_boolean unique set uniqueItems: unique end |
#xor(other) ⇒ Jimmy::Schema Also known as: ^
Combine this schema with another schema using a oneOf
schema. If this schema’s only property is oneOf
, its items will be flattened into the new schema.
Since #^ is an alias of #xor
, the following two statements are equivalent:
schema.xor(other)
schema ^ other
78 79 80 |
# File 'lib/jimmy/schema/operators.rb', line 78 def xor(other) make_new_composite 'oneOf', other end |