h1. Ruby JSON Schema Validator This library is intended to provide Ruby with an interface for validating JSON objects against a JSON schema conforming to "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04. Legacy support for "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03, "JSON Schema Draft 2":http://tools.ietf.org/html/draft-zyp-json-schema-02, and "JSON Schema Draft 1":http://tools.ietf.org/html/draft-zyp-json-schema-01 is also included. h2. Version 2.0.0 Upgrade Notes Please be aware that the upgrade to version 2.0.0 will use Draft-04 *by default*, so schemas that do not declare a validator using the $schema keyword will use Draft-04 now instead of Draft-03. This is the reason for the major version upgrade. h2. Dependencies The JSON::Schema library has no dependencies if the validation methods are called using Ruby objects. However, either the json or the yajl-ruby gem needs to be installed to validate JSON strings or files containing JSON data. h2. Installation From rubygems.org:
gem install json-schema
From the git repo:
$ gem build json-schema.gemspec
$ gem install json-schema-2.0.4.gem
h2. Usage Three base validation methods exist: validate, validate!, and fully_validate. The first returns a boolean on whether a validation attempt passes and the second will throw a JSON::Schema::ValidationError with an appropriate message/trace on where the validation failed. The third validation method does not immediately fail upon a validation error and instead builds an array of validation errors return when validation is complete. All methods take two arguments, which can be either a JSON string, a file containing JSON, or a Ruby object representing JSON data. The first argument to these methods is always the schema, the second is always the data to validate. An optional third options argument is also accepted; available options are used in the examples below. By default, the validator uses the "JSON Schema Draft 4":http://tools.ietf.org/html/draft-zyp-json-schema-04 specification for validation; however, the user is free to specify additional specifications or extend existing ones. Legacy support for Draft 1, Draft 2, and Draft 3 is included by either passing an optional :version parameter to the validate method (set either as :draft1 or draft2), or by declaring the $schema attribute in the schema and referencing the appropriate specification URI. Note that the $schema attribute takes precedence over the :version option during parsing and validation. h3. Validate Ruby objects against a Ruby schema
require 'rubygems'
require 'json-schema'

schema = {
  "type" => "object",
  "required" => ["a"],
  "properties" => {
    "a" => {"type" => "integer"}
  }
}

data = {
  "a" => 5
}

JSON::Validator.validate(schema, data)
h3. Validate a JSON string against a JSON schema file
require 'rubygems'
require 'json-schema'

JSON::Validator.validate('schema.json', '{"a" : 5}')
h3. Validate a list of objects against a schema that represents the individual objects
require 'rubygems'
require 'json-schema'

data = ['user','user','user']
JSON::Validator.validate('user.json', data, :list => true)
h3. Catch a validation error and print it out
require 'rubygems'
require 'json-schema'

schema = {
  "type" => "object",
  "required" => ["a"],
  "properties" => {
    "a" => {"type" => "integer"}
  }
}

data = {
  "a" => "taco"
}

begin
  JSON::Validator.validate!(schema, data)
rescue JSON::Schema::ValidationError
  puts $!.message
end
h3. Fully validate against a schema and catch all errors
require 'rubygems'
require 'json-schema'

schema = {
  "type" => "object",
  "required" => ["a","b"],
  "properties" => {
    "a" => {"type" => "integer"},
    "b" => {"type" => "string"}
  }
}

data = {
  "a" => "taco"
}

errors = JSON::Validator.fully_validate(schema, data)

# ["The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", "The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#"]
h3. Fully validate against a schema and catch all errors as objects
require 'rubygems'
require 'json-schema'

schema = {
  "type" => "object",
  "required" => ["a","b"],
  "properties" => {
    "a" => {"type" => "integer"},
    "b" => {"type" => "string"}
  }
}

data = {
  "a" => "taco"
}

errors = JSON::Validator.fully_validate(schema, data, :errors_as_objects => true)

# [{:message=>"The property '#/a' of type String did not match the following type: integer in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Type", :fragment=>"#/a"}, {:message=>"The property '#/' did not contain a required property of 'b' in schema 03179a21-197e-5414-9611-e9f63e8324cd#", :schema=>#, :failed_attribute=>"Properties", :fragment=>"#/"}]

h3. Validate a JSON object against a JSON schema object, while also validating the schema itself
require 'rubygems'
require 'json-schema'

schema = {
  "type" => "object",
  "required" => ["a"],
  "properties" => {
    "a" => {"type" => "integer"}  # This will fail schema validation!
  }
}

data = {
  "a" => 5
}

JSON::Validator.validate(schema, data, :validate_schema => true)
h3. Validate a JSON object against a JSON schema object, while inserting default values from the schema With the :insert_defaults option set to true any missing property that has a default value specified in the schema will be inserted into the validated data. The inserted default value is validated hence catching a schema that specifies an invalid default value.
require 'rubygems'
require 'json-schema'

schema = {
  "type" => "object",
  "required" => ["a"],
  "properties" => {
    "a" => {"type" => "integer", "default" => 42},
    "b" => {"type" => "integer"}
  }
}

# Would not normally validate because "a" is missing and required by schema,
# but "default" option allows insertion of valid default.
data = {
  "b" => 5
}

JSON::Validator.validate(schema, data)
# false

JSON::Validator.validate(schema, data, :insert_defaults => true)
# true
# data = {
#   "a" => 42,
#   "b" => 5
# }

h3. Validate an object against a JSON Schema Draft 2 schema
require 'rubygems'
require 'json-schema'

schema = {
  "type" => "object",
  "properties" => {
    "a" => {"type" => "integer", "optional" => true}
  }
}

data = {
  "a" => 5
}

JSON::Validator.validate(schema, data, :version => :draft2)
h3. Extend an existing schema and validate against it For this example, we are going to extend the "JSON Schema Draft 3":http://tools.ietf.org/html/draft-zyp-json-schema-03 specification by adding a 'bitwise-and' property for validation.
require 'rubygems'
require 'json-schema'

class BitwiseAndAttribute < JSON::Schema::Attribute
  def self.validate(current_schema, data, fragments, processor, validator, options = {})
    if data.is_a?(Integer) && data & current_schema.schema['bitwise-and'].to_i == 0
      message = "The property '#{build_fragment(fragments)}' did not evaluate  to true when bitwise-AND'd with  #{current_schema.schema['bitwise-or']}"
      raise JSON::Schema::ValidationError.new(message, fragments, current_schema)
    end
  end
end

class ExtendedSchema < JSON::Schema::Validator
  def initialize
    super
    extend_schema_definition("http://json-schema.org/draft-03/schema#")
    @attributes["bitwise-and"] = BitwiseAndAttribute
    @uri = URI.parse("http://test.com/test.json")
  end

  JSON::Validator.register_validator(self.new)
end

schema = {
  "$schema" => "http://test.com/test.json",
  "properties" => {
    "a" => {
      "bitwise-and" => 1
    },
    "b" => {
      "type" => "string"
    }
  }
}

data = {
  "a" => 0
}

data = {"a" => 1, "b" => "taco"}
JSON::Validator.validate(schema,data) # => true
data = {"a" => 1, "b" => 5}
JSON::Validator.validate(schema,data) # => false
data = {"a" => 0, "b" => "taco"}
JSON::Validator.validate(schema,data) # => false
h2. JSON Backends The JSON Schema library currently supports the json and yajl-ruby backend JSON parsers. If either of these libraries are installed, they will be automatically loaded and used to parse any JSON strings supplied by the user. If more than one of the supported JSON backends are installed, the yajl-ruby parser is used by default. This can be changed by issuing the following before validation:
JSON::Validator.json_backend = :json
Optionally, the JSON Schema library supports using the MultiJSON library for selecting JSON backends. If the MultiJSON library is installed, it will be autoloaded. h2. Notes The 'format' attribute is only validated for the following values: * date-time * date * time * ip-address * ipv6 All other 'format' attribute values are simply checked to ensure the instance value is of the correct datatype (e.g., an instance value is validated to be an integer or a float in the case of 'utc-millisec'). Additionally, JSON::Validator does not handle any json hyperschema attributes.