class Validator::Validator
The Validator
class is used to validate a JSON body based on a schema which is a Hash
that describes the structure of the body.
Public Class Methods
Source
# File lib/opennebula/flow/validator.rb, line 117 def initialize(opts = {}) @opts = { :default_values => true, :delete_extra_properties => false, :allow_extra_properties => false }.merge(opts) end
@param [Hash] opts the options to validate a body @option opts [Boolean] :default_values Set default values if the schema
specifies it (if true)
@option opts [Boolean] :delete_extra_properties If the body contains properties
not specified in the schema delete them from the body (if true) or raise an exception (if false)
@option opts [Boolean] :allow_extra_properties Allow properties
not specified in the schema
Public Instance Methods
Source
# File lib/opennebula/flow/validator.rb, line 160 def validate!(body, schema, key = '') if schema[:extends] base_schema = schema.delete(:extends) schema = base_schema.deep_merge(schema) end case schema[:type] when :object then validate_object(body, schema, key) when :array then validate_array(body, schema, key) when :string then validate_string(body, schema, key) when :integer then validate_integer(body, schema, key) when :null then validate_null(body, schema, key) when :boolean then validate_boolean(body, schema, key) else raise SchemaException, "Unsupported type #{schema[:type]}" end end
Recursively validate and modify a JSON body based on a schema.
@see tools.ietf.org/html/draft-zyp-json-schema-03
@param [Hash, Array, String, nil] body JSON represented as Ruby objects @param [Hash] schema that will be used to validate @param [String] key of the body that will be validated in this step
@return [Hash, Array, String, nil] The modified body
@raise [SchemaException] If the schema is not correctly defined @raise [ParseException] if the body does not meet the schema definition
@example Validate a User
schema = { :type => :object, :properties => { 'username' => { :type => :string } } } hash = { 'username' => 'pepe' } Validator.validate!(hash, schema) #=> {'username' => 'pepe'}
@note The parameter body will be modified @note Schema options supported
:extends :type => [:object, :array, :string, :null]
Private Instance Methods
Source
# File lib/opennebula/flow/validator.rb, line 500 def check_enum(body_value, schema_string, schema_key) if schema_string[:enum].include?(body_value) body_value else raise ParseException, "KEY: '#{schema_key}' must be one of"\ " #{schema_string[:enum].join(', ')};" end end
Validate an string enum
@param [String] body_value to be validated @param [Hash] schema_string of the object to validate the body @param [String] schema_key of the body that will be validated in this step
@return [String] The modified body
@raise [ParseException] if the body does not meet the schema definition
@example Validate array
schema = { :type => :string, :enum => ['juan', 'luis'] } body = "juan" Validator.check_enum(body, schema) #=> "juan"
@note The parameter body will be modified @note Schema options supported
:enum
Source
# File lib/opennebula/flow/validator.rb, line 459 def check_format(body_value, schema_string, schema_key) case schema_string[:format] when :uri begin require 'uri' URI.parse(body_value) rescue URI::InvalidURIError raise ParseException, "KEY: '#{schema_key}' must be a valid URL;" end body_value end body_value end
Validate an string format
@param [String] body_value to be validated @param [Hash] schema_string of the object to validate the body @param [String] schema_key of the body that will be validated in this step
@return [String] The modified body
@raise [ParseException] if the body does not meet the schema definition
@example Validate array
schema = { :type => :string, :format => :url } body = "http://localhost:4567" Validator.check_format(body, schema) #=> "http://localhost:4567"
@note The parameter body will be modified @note Schema options supported
:url
Source
# File lib/opennebula/flow/validator.rb, line 534 def check_regex(body_value, schema_string, schema_key) if schema_string[:regex] =~ body_value body_value else raise( ParseException, "KEY: '#{schema_key}' must match regexp #{schema_string[:regex].inspect};" ) end end
Validate an string regex
@param [String] body_value to be validated @param [Hash] schema_string of the object to validate the body @param [String] schema_key of the body that will be validated in this step
@return [String] The modified body
@raise [ParseException] if the body does not meet the schema definition
@example Validate array
schema = { :type => :string, :regex => /^\w+$/ } body = "juan" Validator.check_regex(body, schema) #=> "juan"
@note The parameter body will be modified @note Schema options supported
:enum
Source
# File lib/opennebula/flow/validator.rb, line 277 def validate_array(body, schema_array, schema_key) unless body.instance_of?(Array) raise ParseException, "KEY: '#{schema_key}' must be an Array;" end return body if schema_array[:items].empty? body.collect do |body_item| validate!(body_item, schema_array[:items], schema_key) end end
Validate an array type
@param [Array] body to be validated @param [Hash] schema_array of the object to validate the body @param [String] schema_key of the body that will be validated in this step
@return [Hash] The modified body
@raise [ParseException] if the body does not meet the schema definition
@example Validate array
schema = { :type => :array, :items => { :type => :string } } body = ['pepe', 'luis', 'juan'] Validator.validate_array(body, schema) #=> 'username' => ['pepe', 'luis', 'juan']
@note The parameter body will be modified @note Schema options supported
:items
Source
# File lib/opennebula/flow/validator.rb, line 384 def validate_boolean(body, schema_boolean, schema_key) if body != true && body != false raise ParseException, "KEY: '#{schema_key}' is not allowed in #{schema_boolean};" end body end
Validate an boolean type
@param [Object] body to be validated @param [Hash] schema_boolean of the object to validate the body @param [String] schema_key of the body that will be validated in this step
@return [nil]
@raise [ParseException] if the body is not a boolean
@example Validate array
schema = { :type => :boolean } body = true Validator.validate_boolean(body, schema) #=> nil
Source
# File lib/opennebula/flow/validator.rb, line 310 def validate_integer(body, schema_array, schema_key) value = Integer(body) if schema_array[:maximum] excl = schema_array[:exclusiveMaximum] max = schema_array[:maximum] if !(excl ? value < max : value <= max) raise ParseException, "KEY: '#{schema_key}' must be "\ "lower than #{excl ? '' : 'or equal to'} #{max};" end end if schema_array[:minimum] excl = schema_array[:exclusiveMinimum] min = schema_array[:minimum] if !(excl ? value > min : value >= min) raise ParseException, "KEY: '#{schema_key}' must be "\ "greater than #{excl ? '' : 'or equal to'} #{min};" end end value rescue ArgumentError raise ParseException, "KEY: '#{schema_key}' must be an Integer;" end
Validate an integer type
@param [Array] body to be validated @param [Hash] schema_array of the object to validate the body @param [String] schema_key of the body that will be validated in this step
@return [Hash] The modified body
@raise [ParseException] if the body does not meet the schema definition
@example Validate array
schema = { :type => :integer } body = 5 Validator.validate_integer(body, schema) #=> 5
Source
# File lib/opennebula/flow/validator.rb, line 357 def validate_null(body, schema_null, schema_key) return if body.nil? raise ParseException, "KEY: '#{schema_key}' is not allowed in #{schema_null};" end
Validate an null type
@param [nil] body to be validated @param [Hash] schema_null of the object to validate the body @param [String] schema_key of the body that will be validated in this step
@return [nil]
@raise [ParseException] if the body is not nil
@example Validate array
schema = { :type => :null } body = nil Validator.validate_null(body, schema) #=> nil
Source
# File lib/opennebula/flow/validator.rb, line 210 def validate_object(body, schema_object, key) unless body.is_a?(Hash) raise ParseException, "KEY: '#{key}' must be an Object;" end return body if schema_object[:properties].empty? new_body = body.dup schema_object[:properties].each do |schema_key, schema_value| body_value = new_body.delete(schema_key) if body_value body[schema_key] = validate!(body_value, schema_value, schema_key) else if schema_value[:required] raise ParseException, "Mandatory document key '#{schema_key} (#{schema_value[:type]})' is missing from #{JSON.dump(body)}" end if @opts[:default_values] && schema_value[:default] body[schema_key] = schema_value[:default] end end end # raise error if body.keys is not empty unless new_body.keys.empty? if @opts[:delete_extra_properties] new_body.keys.each {|key| body.delete(key) } else return body if @opts[:allow_extra_properties] raise ParseException, "The following keys are not allowed: #{new_body.keys.join(', ')};" end end body end
Validate an object type
@param [Hash] body to be validated @param [Hash] schema_object of the objectto validate the body @param [String] key of the body that will be validated in this step
@return [Hash] The modified body
@raise [ParseException] if the body does not meet the schema definition
@example Validate with default values
schema_body = { :type => :object, :properties => { 'username' => { :type => :string, :default => 'def' } } body = {} Validator.validate_object(body, schema_body) #=> {'username' => 'def'}
@note The parameter body will be modified @note Schema options supported
:properties :required :default
Source
# File lib/opennebula/flow/validator.rb, line 418 def validate_string(body, schema_string, schema_key) unless body.instance_of?(String) raise ParseException, "KEY: '#{schema_key}' must be a String;" end if schema_string[:format] check_format(body, schema_string, schema_key) elsif schema_string[:enum] check_enum(body, schema_string, schema_key) elsif schema_string[:regex] check_regex(body, schema_string, schema_key) else body end end
Validate an string type
@param [String] body to be validated @param [Hash] schema_string of the object to validate the body @param [String] schema_key of the body that will be validated in this step
@return [String] The modified body
@raise [ParseException] if the body does not meet the schema definition
@example Validate array
schema = { :type => :string } body = "pepe" Validator.validate_string(body, schema) #=> "pepe"
@note The parameter body will be modified @note Schema options supported
:format :enum :regex