• Stars
    star
    1,447
  • Rank 31,252 (Top 0.7 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 13 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Ruby JSON Schema Validator

Ruby JSON Schema Validator

License Test Release RubyGem Version RubyGem Downloads Donated by Iain Beeston

This library is intended to provide Ruby with an interface for validating JSON objects against a JSON schema conforming to JSON Schema Draft 6. Legacy support for JSON Schema Draft 4, JSON Schema Draft 3, JSON Schema Draft 2, and JSON Schema Draft 1 is also included.

Additional Resources

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.

Version 3.0.0 Upgrade Notes

All individual changes are documented in the CHANGELOG.md. The biggest change is that the new version only supports Ruby 2.5 and newer. Take a look into the gemspec file to see the currently supported Ruby version and also .github/workflows/test.yml to see the Ruby versions we test on.

Installation

From rubygems.org:

gem install json-schema

From the git repo:

gem build json-schema.gemspec
gem install json-schema-*.gem

Validation

Three base validation methods exist:

  1. validate: returns a boolean on whether a validation attempt passes
  2. validate!: throws a JSON::Schema::ValidationError with an appropriate message/trace on where the validation failed
  3. fully_validate: 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 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.

For further information on json schema itself refer to Understanding JSON Schema.

Basic Usage

require "json-schema"

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

#
# validate ruby objects against a ruby schema
#

# => true
JSON::Validator.validate(schema, { "a" => 5 })
# => false
JSON::Validator.validate(schema, {})

#
# validate a json string against a json schema file
#

require "json"
File.write("schema.json", JSON.dump(schema))

# => true
JSON::Validator.validate('schema.json', '{ "a": 5 }')

#
# raise an error when validation fails
#

# => "The property '#/a' of type String did not match the following type: integer"
begin
  JSON::Validator.validate!(schema, { "a" => "taco" })
rescue JSON::Schema::ValidationError => e
  e.message
end

#
# return an array of error messages when validation fails
#

# => ["The property '#/a' of type String did not match the following type: integer in schema 18a1ffbb-4681-5b00-bd15-2c76aee4b28f"]
JSON::Validator.fully_validate(schema, { "a" => "taco" })

Advanced Options

require "json-schema"

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

#
# with the `:list` option, a list can be validated against a schema that represents the individual objects
#

# => true
JSON::Validator.validate(schema, [{"a" => 1}, {"a" => 2}, {"a" => 3}], :list => true)
# => false
JSON::Validator.validate(schema, [{"a" => 1}, {"a" => 2}, {"a" => 3}])

#
# with the `:errors_as_objects` option, `#fully_validate` returns errors as hashes instead of strings
#

# => [{:schema=>#<Addressable::URI:0x3ffa69cbeed8 URI:18a1ffbb-4681-5b00-bd15-2c76aee4b28f>, :fragment=>"#/a", :message=>"The property '#/a' of type String did not match the following type: integer in schema 18a1ffbb-4681-5b00-bd15-2c76aee4b28f", :failed_attribute=>"TypeV4"}]
JSON::Validator.fully_validate(schema, { "a" => "taco" }, :errors_as_objects => true)

#
# with the `:strict` option, all properties are considered to have `"required": true` and all objects `"additionalProperties": false`
#

# => true
JSON::Validator.validate(schema, { "a" => 1, "b" => { "x" => 2 } }, :strict => true)
# => false
JSON::Validator.validate(schema, { "a" => 1, "b" => { "x" => 2 }, "c" => 3 }, :strict => true)
# => false
JSON::Validator.validate(schema, { "a" => 1 }, :strict => true)

#
# with the `:fragment` option, only a fragment of the schema is used for validation
#

# => true
JSON::Validator.validate(schema, { "x" => 1 }, :fragment => "#/properties/b")
# => false
JSON::Validator.validate(schema, { "x" => 1 })

#
# with the `:validate_schema` option, the schema is validated (against the json schema spec) before the json is validated (against the specified schema)
#

# => true
JSON::Validator.validate(schema, { "a" => 1 }, :validate_schema => true)
# => false
JSON::Validator.validate({ "required" => true }, { "a" => 1 }, :validate_schema => true)

#
# with the `:insert_defaults` option, any undefined values in the json that have a default in the schema are replaced with the default before validation
#

# => true
JSON::Validator.validate(schema, {}, :insert_defaults => true)
# => false
JSON::Validator.validate(schema, {})

#
# with the `:version` option, schemas conforming to older drafts of the json schema spec can be used
#

v2_schema = {
  "type" => "object",
  "properties" => {
    "a" => {
      "type" => "integer"
    }
  }
}

# => false
JSON::Validator.validate(v2_schema, {}, :version => :draft2)
# => true
JSON::Validator.validate(v2_schema, {})

#
# with the `:parse_data` option set to false, the json must be a parsed ruby object (not a json text, a uri or a file path)
#

# => true
JSON::Validator.validate(schema, { "a" => 1 }, :parse_data => false)
# => false
JSON::Validator.validate(schema, '{ "a": 1 }', :parse_data => false)

#
# with the `:parse_integer` option set to false, the integer value given as string will not be parsed.
#

# => true
JSON::Validator.validate({type: "integer"}, "23")
# => false
JSON::Validator.validate({type: "integer"}, "23", parse_integer: false)
# => true
JSON::Validator.validate({type: "string"}, "123", parse_integer: false)
# => false
JSON::Validator.validate({type: "string"}, "123")

#
# with the `:json` option, the json must be an unparsed json text (not a hash, a uri or a file path)
#

# => true
JSON::Validator.validate(schema, '{ "a": 1 }', :json => true)
# => "no implicit conversion of Hash into String"
begin
  JSON::Validator.validate(schema, { "a" => 1 }, :json => true)
rescue TypeError => e
  e.message
end

#
# with the `:uri` option, the json must be a uri or file path (not a hash or a json text)
#

File.write("data.json", '{ "a": 1 }')

# => true
JSON::Validator.validate(schema, "data.json", :uri => true)
# => "Can't convert Hash into String."
begin
  JSON::Validator.validate(schema, { "a"  => 1 }, :uri => true)
rescue TypeError => e
  e.message
end

#
# with the `:clear_cache` option set to true, the internal cache of schemas is
# cleared after validation (otherwise schemas are cached for efficiency)
#

File.write("schema.json", v2_schema.to_json)

# => true
JSON::Validator.validate("schema.json", {})

File.write("schema.json", schema.to_json)

# => true
JSON::Validator.validate("schema.json", {}, :clear_cache => true)

# => false
JSON::Validator.validate("schema.json", {})

Extending Schemas

For this example, we are going to extend the JSON Schema Draft 3 specification by adding a 'bitwise-and' property for validation.

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']}"
      validation_error(processor, message, fragments, current_schema, self, options[:record_errors])
    end
  end
end

class ExtendedSchema < JSON::Schema::Draft3
  def initialize
    super
    @attributes["bitwise-and"] = BitwiseAndAttribute
    @uri = JSON::Util::URI.parse("http://test.com/test.json")
    @names = ["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

Custom format validation

The JSON schema standard allows custom formats in schema definitions which should be ignored by validators that do not support them. JSON::Schema allows registering procs as custom format validators which receive the value to be checked as parameter and must raise a JSON::Schema::CustomFormatError to indicate a format violation. The error message will be prepended by the property name, e.g. The property '#a'

require "json-schema"

format_proc = -> value {
  raise JSON::Schema::CustomFormatError.new("must be 42") unless value == "42"
}

# register the proc for format 'the-answer' for draft4 schema
JSON::Validator.register_format_validator("the-answer", format_proc, ["draft4"])

# omitting the version parameter uses ["draft1", "draft2", "draft3", "draft4"] as default
JSON::Validator.register_format_validator("the-answer", format_proc)

# deregistering the custom validator
# (also ["draft1", "draft2", "draft3", "draft4"] as default version)
JSON::Validator.deregister_format_validator('the-answer', ["draft4"])

# shortcut to restore the default formats for validators (same default as before)
JSON::Validator.restore_default_formats(["draft4"])

# with the validator registered as above, the following results in
# ["The property '#a' must be 42"] as returned errors
schema = {
  "$schema" => "http://json-schema.org/draft-04/schema#",
  "properties" => {
    "a" => {
      "type" => "string",
      "format" => "the-answer",
    }
  }
}
errors = JSON::Validator.fully_validate(schema, {"a" => "23"})

Validating a JSON Schema

To validate that a JSON Schema conforms to the JSON Schema standard, you need to validate your schema against the metaschema for the appropriate JSON Schema Draft. All of the normal validation methods can be used for this. First retrieve the appropriate metaschema from the internal cache (using JSON::Validator.validator_for_name() or JSON::Validator.validator_for_uri()) and then simply validate your schema against it.

require "json-schema"

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

metaschema = JSON::Validator.validator_for_name("draft4").metaschema
# => true
JSON::Validator.validate(metaschema, schema)

Controlling Remote Schema Reading

In some cases, you may wish to prevent the JSON Schema library from making HTTP calls or reading local files in order to resolve $ref schemas. If you fully control all schemas which should be used by validation, this could be accomplished by registering all referenced schemas with the validator in advance:

schema = JSON::Schema.new(some_schema_definition, Addressable::URI.parse('http://example.com/my-schema'))
JSON::Validator.add_schema(schema)

If more extensive control is necessary, the JSON::Schema::Reader instance used can be configured in a few ways:

# Change the default schema reader used
JSON::Validator.schema_reader = JSON::Schema::Reader.new(:accept_uri => true, :accept_file => false)

# For this validation call, use a reader which only accepts URIs from my-website.com
schema_reader = JSON::Schema::Reader.new(
  :accept_uri => proc { |uri| uri.host == 'my-website.com' }
)
JSON::Validator.validate(some_schema, some_object, :schema_reader => schema_reader)

The JSON::Schema::Reader interface requires only an object which responds to read(string) and returns a JSON::Schema instance. See the API documentation for more information.

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.

Notes

The 'format' attribute is only validated for the following values:

  • date-time
  • date
  • time
  • ip-address (IPv4 address in draft1, draft2 and draft3)
  • ipv4 (IPv4 address in draft4)
  • ipv6
  • uri

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.

Transfer Notice

This plugin was originally authored by Iain Beeston. The maintainer preferred that Vox Pupuli take ownership of the module for future improvement and maintenance. Existing pull requests and issues were transferred, please fork and continue to contribute here.

License

This gem is licensed under the MIT license.

Release information

To make a new release, please do:

  • update the version in VERSION.yml
  • Install gems with bundle install --with release --path .vendor
  • generate the changelog with bundle exec rake changelog
  • Check if the new version matches the closed issues/PRs in the changelog
  • Create a PR with it
  • After it got merged, push a tag. GitHub actions will do the actual release to rubygems and GitHub Packages

More Repositories

1

puppetboard

Web frontend for PuppetDB
Python
698
star
2

hiera-eyaml

A backend for Hiera that provides per-value asymmetric encryption of sensitive data
Ruby
524
star
3

puppet-nginx

Puppet Module to manage NGINX on various UNIXes
Ruby
468
star
4

puppet-elasticsearch

Elasticsearch Puppet module
Ruby
406
star
5

beaker

Puppet Acceptance Testing Harness
Ruby
368
star
6

puppet-jenkins

Puppet module for Jenkins
Ruby
276
star
7

puppet-python

Puppet module for installing and managing Python, pip, virtualenvs and Gunicorn virtual hosts.
Ruby
197
star
8

puppet-logstash

Puppet module to manage Logstash
Puppet
192
star
9

puppet-rabbitmq

RabbitMQ Puppet Module
Ruby
174
star
10

puppet-mcollective

MCollective Server and Client Puppet Module
Ruby
122
star
11

puppet-consul

A Puppet Module to Manage Consul
Ruby
120
star
12

puppet-openvpn

OpenVPN module for puppet including client config/cert creation
Ruby
113
star
13

puppet-nodejs

Puppet module to install nodejs and global npm packages
Ruby
112
star
14

modulesync

Synchronize common files across your Git repositories.
Ruby
101
star
15

vagrant-librarian-puppet

A Vagrant plugin to install Puppet modules using Librarian-Puppet.
Ruby
101
star
16

puppet-r10k

Setup and configure r10k for use with git based environments in puppet
Ruby
98
star
17

pypuppetdb

Python library for working with the PuppetDB API
Python
93
star
18

puppet-mongodb

mongodb installation
Ruby
92
star
19

puppet-ghostbuster

👻 Dead code detector for Puppet
Ruby
89
star
20

puppet-letsencrypt

A Puppet module to install the Letsencrypt client and request certificates.
Ruby
86
star
21

puppet-php

Generic Puppet module to manage PHP on many platforms
Puppet
85
star
22

puppet-mode

Edit Puppet manifests with GNU Emacs 24
Emacs Lisp
77
star
23

puppet-gitlab

Puppet module to manage Gitlab (Omnibus)
Puppet
74
star
24

puppet-postfix

Puppet postfix module
HTML
72
star
25

puppet-collectd

Collectd module for Puppet
Ruby
70
star
26

puppet-syntax

Syntax checks for Puppet manifests and templates
Ruby
68
star
27

puppet-blacksmith

Ruby Gem with Puppet Module utilities
Ruby
68
star
28

puppet-network

Types and providers to manage network interfaces
Ruby
68
star
29

puppet-augeasproviders

Alternative Augeas-based providers for Puppet
Ruby
65
star
30

puppet-system

Manage Linux system resources and services from hiera configuration
Puppet
65
star
31

puppet-jira

Atlassian JIRA Puppet Module
Ruby
61
star
32

puppet-prometheus

Puppet module for prometheus
Puppet
60
star
33

puppet-archive

Compressed archive file download and extraction with native types/providers for Windows and Unix
Ruby
59
star
34

beaker-rspec

beaker-rspec is a bridge between the puppet acceptance test harness
Ruby
58
star
35

rspec-puppet-facts

Simplify your unit tests by looping on every supported Operating System and populating facts.
Ruby
58
star
36

puppet-puppetboard

Puppet module to install and manage puppetboard
Puppet
53
star
37

puppet-staging

⛔️ Deprecated in favor of puppet-archive
Ruby
51
star
38

puppet-pxe

Puppet module for deploying a PXE boot server
Puppet
49
star
39

hiera-eyaml-gpg

GPG encryption backend for the hiera-eyaml module
Ruby
49
star
40

puppet-systemd

Puppet module to manage systemd
Ruby
49
star
41

puppet-selinux

Puppet Module to manage SELinux on RHEL machines
Ruby
49
star
42

puppet-keepalived

Puppet Module to manage Keepalived
Ruby
48
star
43

puppet-prometheus_reporter

A prometheus Puppet reports exporter for Puppet
Ruby
48
star
44

puppet-iis

Module to mange IIS with Puppet
Ruby
46
star
45

puppet-corosync

Sets up and manages Corosync.
Ruby
45
star
46

puppet-epel

Setup/configure EPEL (extra repository for enterprise linux) with Puppet
Ruby
42
star
47

puppet-dhcp

Puppet module for deploying dhcp
Ruby
42
star
48

puppet-redis

Puppet Module to manage Redis
Ruby
40
star
49

puppet-openssl

Puppet OpenSSL module
Ruby
39
star
50

puppet-pkgng

A Puppet package provider for FreeBSD's PkgNG package manager.
Ruby
39
star
51

puppet-firewalld

Puppet module for managing firewalld
Ruby
39
star
52

puppet-splunk

Manage Splunk servers and forwarders using Puppet
Ruby
39
star
53

puppet-rundeck

Module for managing the installatation and configuration of the rundeck orchestration tool
Ruby
38
star
54

puppet-openldap

Manage OpenLDAP with Puppet
Ruby
35
star
55

puppet-vmwaretools

Puppet module to manage VMware Operating System Specific Packages for VMware tools installation.
Puppet
35
star
56

puppet-snmp

Puppet module to manage Net-SNMP.
Ruby
34
star
57

puppet-unattended_upgrades

Unattended-upgrades for APT
Ruby
33
star
58

puppet-dnsquery

DNS query functions for Puppet
Ruby
32
star
59

puppet-hiera

Hiera hierarchy module for templating `hiera.yaml`
Ruby
32
star
60

puppet-kafka

The kafka module for managing the installation and configuration of Apache Kafka
Puppet
30
star
61

puppet-fail2ban

This module installs, configures and manages the Fail2ban service.
Ruby
30
star
62

ra10ke

Rake tasks related to R10K and Puppetfile
Ruby
29
star
63

puppet-windowsfeature

Library that uses ServerAdministration api that comes with Windows Server 2008 and Windows Server 2012 to add / remove windows features
Ruby
29
star
64

puppet-catalog-diff-viewer

A viewer for the puppet-catalog-diff tool
JavaScript
28
star
65

puppet-unbound

Puppet module for deploying the swiss-army of DNS, Unbound
Ruby
28
star
66

puppet-wildfly

Puppet module to install, configure and manage Wildfly (8/9/10+), JBoss EAP (6.1+/7.0+) and some Wildfly based products like apiman, Keycloak and Infinispan.
Ruby
28
star
67

metadata-json-lint

Tool to check the validity of Puppet metadata.json files
Ruby
27
star
68

hiera-file

File backend for Hiera
Ruby
26
star
69

puppet-vault_lookup

Ruby
25
star
70

puppetdb-ruby

Ruby client library for interacting with PuppetDB API
Ruby
24
star
71

puppet-alternatives

Manage Debian alternatives links
Ruby
24
star
72

puppet-telegraf

A Puppet module for installing and configuring InfluxData's Telegraf
Ruby
24
star
73

puppet-healthcheck

Puppet resources to evaluate the health and status of things.
Ruby
22
star
74

puppet-puppetserver

Puppet module for puppetserver
Ruby
21
star
75

puppet-confluence

A puppet module to install confluence
Ruby
20
star
76

puppet-drbd

Basic module for configuring active-passive drbd resources
Puppet
20
star
77

puppet-stash

A puppet module to install atlassian stash
Ruby
19
star
78

puppet-kmod

manage kernel module with puppet
Ruby
18
star
79

puppet-mrepo

Puppet module for creating and managing RPM based repository mirrors.
Puppet
17
star
80

puppet-ssh_keygen

Generation of ssh keys with ssh-keygen
Ruby
17
star
81

puppet-windows_firewall

puppet module for configuring the windows firewall
Ruby
17
star
82

puppet-gluster

Create and manage Gluster pools, volumes, and mounts
Ruby
16
star
83

puppet-nomad

Puppet module for managing Nomad
Ruby
16
star
84

puppet-kibana

Kibana Puppet module by Elastic.
Ruby
16
star
85

puppet-filemapper

Map files to puppet resources and back
Ruby
15
star
86

puppet-proxysql

Puppet module to configure ProxySQL
Ruby
15
star
87

puppet-minecraft

Puppet - Minecraft: Separately maintained fork of brannan's puppet-module-minecraft
Ruby
14
star
88

puppet-cron

Puppet module to manage cron jobs via /etc/cron.d
Ruby
14
star
89

puppet-tea

Puppet 4.6 Types: Abstracted & Extracted
Ruby
14
star
90

puppet-ca_cert

A puppet module for managing (non-system) CA certificates.
Ruby
14
star
91

puppet-misp

This module installs and configures MISP (Malware Information Sharing Platform)
HTML
14
star
92

puppet-googleauthenticator

Google-authenticator module for Puppet
Puppet
13
star
93

puppet-chrony

Puppet module for Chrony with Systemd
Ruby
13
star
94

puppet-smokeping

Puppet module to install and configure smokeping. Including target and slave definition
Puppet
13
star
95

puppet-cassandra

Installs Cassandra & DataStax Agent on RHEL/Ubuntu/Debian.
Ruby
13
star
96

puppet-bareos

Puppet Module to manage bareos
Puppet
13
star
97

puppet_webhook

Sinatra-based application that triggers puppet-related commands from VCS Webhook calls
Ruby
13
star
98

puppet-extlib

This module provides functions that are out of scope for stdlib.
Ruby
13
star
99

puppet-gitlab_ci_runner

Module to mange gitlab CI runners. Extracted from https://github.com/voxpupuli/puppet-gitlab
Ruby
13
star
100

puppet-dotnet

puppet module for managing Microsoft .NET
Ruby
12
star