{"id":13411530,"url":"https://github.com/davishmcclurg/json_schemer","last_synced_at":"2025-05-13T22:12:13.498Z","repository":{"id":28506996,"uuid":"118581149","full_name":"davishmcclurg/json_schemer","owner":"davishmcclurg","description":"JSON Schema validator. Supports drafts 4, 6, 7, 2019-09, 2020-12, OpenAPI 3.0, and OpenAPI 3.1.","archived":false,"fork":false,"pushed_at":"2025-02-02T00:54:05.000Z","size":1095,"stargazers_count":425,"open_issues_count":11,"forks_count":65,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-04-30T12:16:50.026Z","etag":null,"topics":["json-schema","json-validation","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davishmcclurg.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-23T08:31:51.000Z","updated_at":"2025-04-29T09:26:21.000Z","dependencies_parsed_at":"2023-10-24T04:45:19.990Z","dependency_job_id":"bfe4d099-4dc0-459c-98d5-e5d5198f8863","html_url":"https://github.com/davishmcclurg/json_schemer","commit_stats":{"total_commits":369,"total_committers":27,"mean_commits":"13.666666666666666","dds":0.2872628726287263,"last_synced_commit":"2a239b61b1e26a2c6c935449265f8566f9bcab98"},"previous_names":[],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davishmcclurg%2Fjson_schemer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davishmcclurg%2Fjson_schemer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davishmcclurg%2Fjson_schemer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davishmcclurg%2Fjson_schemer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davishmcclurg","download_url":"https://codeload.github.com/davishmcclurg/json_schemer/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252316934,"owners_count":21728521,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json-schema","json-validation","ruby"],"created_at":"2024-07-30T20:01:14.285Z","updated_at":"2025-05-13T22:12:13.438Z","avatar_url":"https://github.com/davishmcclurg.png","language":"Ruby","funding_links":[],"categories":["Ruby","Who Uses the Test Suite"],"sub_categories":["Ruby"],"readme":"# JSONSchemer\n\nJSON Schema validator. Supports drafts 4, 6, 7, 2019-09, 2020-12, OpenAPI 3.0, and OpenAPI 3.1.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'json_schemer'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install json_schemer\n\n## Usage\n\n```ruby\nrequire 'json_schemer'\n\nschema = {\n  'type' =\u003e 'object',\n  'properties' =\u003e {\n    'abc' =\u003e {\n      'type' =\u003e 'integer',\n      'minimum' =\u003e 11\n    }\n  }\n}\nschemer = JSONSchemer.schema(schema)\n\n# true/false validation\n\nschemer.valid?({ 'abc' =\u003e 11 })\n# =\u003e true\n\nschemer.valid?({ 'abc' =\u003e 10 })\n# =\u003e false\n\n# error validation (`validate` returns an enumerator)\n\nschemer.validate({ 'abc' =\u003e 10 }).to_a\n# =\u003e [{\"data\"=\u003e10,\n#      \"data_pointer\"=\u003e\"/abc\",\n#      \"schema\"=\u003e{\"type\"=\u003e\"integer\", \"minimum\"=\u003e11},\n#      \"schema_pointer\"=\u003e\"/properties/abc\",\n#      \"root_schema\"=\u003e{\"type\"=\u003e\"object\", \"properties\"=\u003e{\"abc\"=\u003e{\"type\"=\u003e\"integer\", \"minimum\"=\u003e11}}},\n#      \"type\"=\u003e\"minimum\",\n#      \"error\"=\u003e\"number at `/abc` is less than: 11\"}]\n\n# default property values\n\ndata = {}\nJSONSchemer.schema(\n  {\n    'properties' =\u003e {\n      'foo' =\u003e {\n        'default' =\u003e 'bar'\n      }\n    }\n  },\n  insert_property_defaults: true\n).valid?(data)\ndata\n# =\u003e {\"foo\"=\u003e\"bar\"}\n\n# schema files\n\nrequire 'pathname'\n\nschema = Pathname.new('/path/to/schema.json')\nschemer = JSONSchemer.schema(schema)\n\n# schema json string\n\nschema = '{ \"type\": \"integer\" }'\nschemer = JSONSchemer.schema(schema)\n\n# schema validation\n\nJSONSchemer.valid_schema?({ '$id' =\u003e 'valid' })\n# =\u003e true\n\nJSONSchemer.validate_schema({ '$id' =\u003e '#invalid' }).to_a\n# =\u003e [{\"data\"=\u003e\"#invalid\",\n#      \"data_pointer\"=\u003e\"/$id\",\n#      \"schema\"=\u003e{\"$ref\"=\u003e\"#/$defs/uriReferenceString\", \"$comment\"=\u003e\"Non-empty fragments not allowed.\", \"pattern\"=\u003e\"^[^#]*#?$\"},\n#      \"schema_pointer\"=\u003e\"/properties/$id\",\n#      \"root_schema\"=\u003e{...meta schema},\n#      \"type\"=\u003e\"pattern\",\n#      \"error\"=\u003e\"string at `/$id` does not match pattern: ^[^#]*#?$\"}]\n\n# subschemas\n\nschema = {\n  'type' =\u003e 'integer',\n  '$defs' =\u003e {\n    'foo' =\u003e {\n      'type' =\u003e 'string'\n    }\n  }\n}\nschemer = JSONSchemer.schema(schema)\n\nschemer.ref('#/$defs/foo').validate(1).to_a\n# =\u003e [{\"data\"=\u003e1,\n#      \"data_pointer\"=\u003e\"\",\n#      \"schema\"=\u003e{\"type\"=\u003e\"string\"},\n#      \"schema_pointer\"=\u003e\"/$defs/foo\",\n#      \"root_schema\"=\u003e{\"type\"=\u003e\"integer\", \"$defs\"=\u003e{\"foo\"=\u003e{\"type\"=\u003e\"string\"}}},\n#      \"type\"=\u003e\"string\",\n#      \"error\"=\u003e\"value at root is not a string\"}]\n\n# schema bundling (https://json-schema.org/draft/2020-12/json-schema-core.html#section-9.3)\n\nschema = {\n  '$id' =\u003e 'http://example.com/schema',\n  'allOf' =\u003e [\n    { '$ref' =\u003e 'schema/one' },\n    { '$ref' =\u003e 'schema/two' }\n  ]\n}\nrefs = {\n  URI('http://example.com/schema/one') =\u003e {\n    'type' =\u003e 'integer'\n  },\n  URI('http://example.com/schema/two') =\u003e {\n    'minimum' =\u003e 11\n  }\n}\nschemer = JSONSchemer.schema(schema, :ref_resolver =\u003e refs.to_proc)\n\nschemer.bundle\n# =\u003e {\"$id\"=\u003e\"http://example.com/schema\",\n#     \"allOf\"=\u003e[{\"$ref\"=\u003e\"schema/one\"}, {\"$ref\"=\u003e\"schema/two\"}],\n#     \"$schema\"=\u003e\"https://json-schema.org/draft/2020-12/schema\",\n#     \"$defs\"=\u003e\n#      {\"http://example.com/schema/one\"=\u003e{\"type\"=\u003e\"integer\", \"$id\"=\u003e\"http://example.com/schema/one\", \"$schema\"=\u003e\"https://json-schema.org/draft/2020-12/schema\"},\n#       \"http://example.com/schema/two\"=\u003e{\"minimum\"=\u003e11, \"$id\"=\u003e\"http://example.com/schema/two\", \"$schema\"=\u003e\"https://json-schema.org/draft/2020-12/schema\"}}}\n```\n\n## Options\n\n```ruby\nJSONSchemer.schema(\n  schema,\n\n  # meta schema to use for vocabularies (keyword behavior) and schema validation\n  # String/JSONSchemer::Schema\n  # 'https://json-schema.org/draft/2020-12/schema': JSONSchemer.draft202012\n  # 'https://json-schema.org/draft/2019-09/schema': JSONSchemer.draft201909\n  # 'http://json-schema.org/draft-07/schema#': JSONSchemer.draft7\n  # 'http://json-schema.org/draft-06/schema#': JSONSchemer.draft6\n  # 'http://json-schema.org/draft-04/schema#': JSONSchemer.draft4\n  # 'http://json-schema.org/schema#': JSONSchemer.draft4\n  # 'https://spec.openapis.org/oas/3.1/dialect/base': JSONSchemer.openapi31\n  # 'json-schemer://openapi30/schema': JSONSchemer.openapi30\n  # default: JSONSchemer.draft202012\n  meta_schema: 'https://json-schema.org/draft/2020-12/schema',\n\n  # validate `format` (https://json-schema.org/draft/2020-12/json-schema-validation.html#section-7)\n  # true/false\n  # default: true\n  format: true,\n\n  # custom formats\n  formats: {\n    'int32' =\u003e proc do |instance, _format|\n      instance.is_a?(Integer) \u0026\u0026 instance.bit_length \u003c= 32\n    end,\n    # disable specific format\n    'email' =\u003e false\n  },\n\n  # custom content encodings\n  # only `base64` is available by default\n  content_encodings: {\n    # return [success, annotation] tuple\n    'urlsafe_base64' =\u003e proc do |instance|\n      [true, Base64.urlsafe_decode64(instance)]\n    rescue\n      [false, nil]\n    end\n  },\n\n  # custom content media types\n  # only `application/json` is available by default\n  content_media_types: {\n    # return [success, annotation] tuple\n    'text/csv' =\u003e proc do |instance|\n      [true, CSV.parse(instance)]\n    rescue\n      [false, nil]\n    end\n  },\n\n  # insert default property values during validation\n  # string keys by default (use `:symbol` to insert symbol keys)\n  # true/false/:symbol\n  # default: false\n  insert_property_defaults: true,\n\n  # modify properties during validation. You can pass one Proc or a list of Procs to modify data.\n  # Proc/[Proc]\n  # default: nil\n  before_property_validation: proc do |data, property, property_schema, _parent|\n    data[property] ||= 42\n  end,\n\n  # modify properties after validation. You can pass one Proc or a list of Procs to modify data.\n  # Proc/[Proc]\n  # default: nil\n  after_property_validation: proc do |data, property, property_schema, _parent|\n    data[property] = Date.iso8601(data[property]) if property_schema.is_a?(Hash) \u0026\u0026 property_schema['format'] == 'date'\n  end,\n\n  # resolve external references\n  # 'net/http'/proc/lambda/respond_to?(:call)\n  # 'net/http': proc { |uri| JSON.parse(Net::HTTP.get(uri)) }\n  # default: proc { |uri| raise UnknownRef, uri.to_s }\n  ref_resolver: 'net/http',\n  \n  # use different method to match regexes\n  # 'ruby'/'ecma'/proc/lambda/respond_to?(:call)\n  # 'ruby': proc { |pattern| Regexp.new(pattern) }\n  # default: 'ruby'\n  regexp_resolver: proc do |pattern|\n    RE2::Regexp.new(pattern)\n  end,\n\n  # output formatting (https://json-schema.org/draft/2020-12/json-schema-core.html#section-12)\n  # 'classic'/'flag'/'basic'/'detailed'/'verbose'\n  # default: 'classic'\n  output_format: 'basic',\n\n  # validate `readOnly`/`writeOnly` keywords (https://spec.openapis.org/oas/v3.0.3#fixed-fields-19)\n  # 'read'/'write'/nil\n  # default: nil\n  access_mode: 'read'\n)\n```\n\n## Global Configuration\n\nConfiguration options can be set globally by modifying `JSONSchemer.configuration`. Global options are applied to any new schemas at creation time (global configuration changes are not reflected in existing schemas). They can be overridden with the regular keyword arguments described [above](#options).\n\n```ruby\n# configuration block\nJSONSchemer.configure do |config|\n  config.regexp_resolver = 'ecma'\nend\n\n# configuration accessors\nJSONSchemer.configuration.insert_property_defaults = true\n```\n\n## Custom Error Messages\n\nError messages can be customized using the `x-error` keyword and/or [I18n](https://github.com/ruby-i18n/i18n) translations. `x-error` takes precedence if both are defined.\n\n### `x-error` Keyword\n\n```ruby\n# override all errors for a schema\nschemer = JSONSchemer.schema({\n  'type' =\u003e 'string',\n  'x-error' =\u003e 'custom error for schema and all keywords'\n})\n\nschemer.validate(1).first\n# =\u003e {\"data\"=\u003e1,\n#     \"data_pointer\"=\u003e\"\",\n#     \"schema\"=\u003e{\"type\"=\u003e\"string\", \"x-error\"=\u003e\"custom error for schema and all keywords\"},\n#     \"schema_pointer\"=\u003e\"\",\n#     \"root_schema\"=\u003e{\"type\"=\u003e\"string\", \"x-error\"=\u003e\"custom error for schema and all keywords\"},\n#     \"type\"=\u003e\"string\",\n#     \"error\"=\u003e\"custom error for schema and all keywords\",\n#     \"x-error\"=\u003etrue}\n\nschemer.validate(1, :output_format =\u003e 'basic')\n# =\u003e {\"valid\"=\u003efalse,\n#     \"keywordLocation\"=\u003e\"\",\n#     \"absoluteKeywordLocation\"=\u003e\"json-schemer://schema#\",\n#     \"instanceLocation\"=\u003e\"\",\n#     \"error\"=\u003e\"custom error for schema and all keywords\",\n#     \"x-error\"=\u003etrue,\n#     \"errors\"=\u003e#\u003cEnumerator: ...\u003e}\n\n# keyword-specific errors\nschemer = JSONSchemer.schema({\n  'type' =\u003e 'string',\n  'minLength' =\u003e 10,\n  'x-error' =\u003e {\n    'type' =\u003e 'custom error for `type` keyword',\n    # special `^` keyword for schema-level error\n    '^' =\u003e 'custom error for schema',\n    # same behavior as when `x-error` is a string\n    '*' =\u003e 'fallback error for schema and all keywords'\n  }\n})\n\nschemer.validate(1).map { _1.fetch('error') }\n# =\u003e [\"custom error for `type` keyword\"]\n\nschemer.validate('1').map { _1.fetch('error') }\n# =\u003e [\"custom error for schema and all keywords\"]\n\nschemer.validate(1, :output_format =\u003e 'basic').fetch('error')\n# =\u003e \"custom error for schema\"\n\n# variable interpolation (instance/instanceLocation/keywordLocation/absoluteKeywordLocation)\nschemer = JSONSchemer.schema({\n  '$id' =\u003e 'https://example.com/schema',\n  'properties' =\u003e {\n    'abc' =\u003e {\n      'type' =\u003e 'string',\n      'x-error' =\u003e \u003c\u003c~ERROR\n        instance: %{instance}\n        instance location: %{instanceLocation}\n        keyword location: %{keywordLocation}\n        absolute keyword location: %{absoluteKeywordLocation}\n      ERROR\n    }\n  }\n})\n\nputs schemer.validate({ 'abc' =\u003e 1 }).first.fetch('error')\n# instance: 1\n# instance location: /abc\n# keyword location: /properties/abc/type\n# absolute keyword location: https://example.com/schema#/properties/abc/type\n```\n\n### I18n\n\nWhen the [I18n gem](https://github.com/ruby-i18n/i18n) is loaded, custom error messages are looked up under the `json_schemer` key. It may be necessary to restart your application after adding the root key because the existence check is cached for performance reasons.\n\nTranslation keys are looked up in this order:\n\n1. `$LOCALE.json_schemer.errors.$ABSOLUTE_KEYWORD_LOCATION`\n2. `$LOCALE.json_schemer.errors.$SCHEMA_ID.$KEYWORD_LOCATION`\n3. `$LOCALE.json_schemer.errors.$KEYWORD_LOCATION`\n4. `$LOCALE.json_schemer.errors.$SCHEMA_ID.$KEYWORD`\n5. `$LOCALE.json_schemer.errors.$SCHEMA_ID.*`\n6. `$LOCALE.json_schemer.errors.$META_SCHEMA_ID.$KEYWORD`\n7. `$LOCALE.json_schemer.errors.$META_SCHEMA_ID.*`\n8. `$LOCALE.json_schemer.errors.$KEYWORD`\n9. `$LOCALE.json_schemer.errors.*`\n\nExample translations file:\n\n```yaml\nen:\n  json_schemer:\n    errors:\n      'https://example.com/schema#/properties/abc/type': custom error for absolute keyword location\n      'https://example.com/schema':\n        '#/properties/abc/type': custom error for keyword location, nested under schema $id\n        'type': custom error for `type` keyword, nested under schema $id\n        '^': custom error for schema, nested under schema $id\n        '*': fallback error for schema and all keywords, nested under schema $id\n      '#/properties/abc/type': custom error for keyword location\n      'http://json-schema.org/draft-07/schema#':\n        'type': custom error for `type` keyword, nested under meta-schema $id ($schema)\n        '^': custom error for schema, nested under meta-schema $id\n        '*': fallback error for schema and all keywords, nested under meta-schema $id ($schema)\n      'type': custom error for `type` keyword\n      '^': custom error for schema\n      # variable interpolation (instance/instanceLocation/keywordLocation/absoluteKeywordLocation)\n      '*': |\n        fallback error for schema and all keywords\n        instance: %{instance}\n        instance location: %{instanceLocation}\n        keyword location: %{keywordLocation}\n        absolute keyword location: %{absoluteKeywordLocation}\n```\n\nAnd output:\n\n```ruby\nrequire 'i18n'\nI18n.locale = :en                                         # $LOCALE=en\n\nschemer = JSONSchemer.schema({\n  '$id' =\u003e 'https://example.com/schema',                  # $SCHEMA_ID=https://example.com/schema\n  '$schema' =\u003e 'http://json-schema.org/draft-07/schema#', # $META_SCHEMA_ID=http://json-schema.org/draft-07/schema#\n  'properties' =\u003e {\n    'abc' =\u003e {\n      'type' =\u003e 'integer'                                 # $KEYWORD=type\n    }                                                     # $KEYWORD_LOCATION=#/properties/abc/type\n  }                                                       # $ABSOLUTE_KEYWORD_LOCATION=https://example.com/schema#/properties/abc/type\n})\n\nschemer.validate({ 'abc' =\u003e 'not-an-integer' }).first\n# =\u003e {\"data\"=\u003e\"not-an-integer\",\n#     \"data_pointer\"=\u003e\"/abc\",\n#     \"schema\"=\u003e{\"type\"=\u003e\"integer\"},\n#     \"schema_pointer\"=\u003e\"/properties/abc\",\n#     \"root_schema\"=\u003e{\"$id\"=\u003e\"https://example.com/schema\", \"$schema\"=\u003e\"http://json-schema.org/draft-07/schema#\", \"properties\"=\u003e{\"abc\"=\u003e{\"type\"=\u003e\"integer\"}}},\n#     \"type\"=\u003e\"integer\",\n#     \"error\"=\u003e\"custom error for absolute keyword location\",\n#     \"i18n\"=\u003etrue\n```\n\nIn the example above, custom error messsages are looked up using the following keys (in order until one is found):\n\n1. `en.json_schemer.errors.'https://example.com/schema#/properties/abc/type'`\n2. `en.json_schemer.errors.'https://example.com/schema'.'#/properties/abc/type'`\n3. `en.json_schemer.errors.'#/properties/abc/type'`\n4. `en.json_schemer.errors.'https://example.com/schema'.type`\n5. `en.json_schemer.errors.'https://example.com/schema'.*`\n6. `en.json_schemer.errors.'http://json-schema.org/draft-07/schema#'.type`\n7. `en.json_schemer.errors.'http://json-schema.org/draft-07/schema#'.*`\n8. `en.json_schemer.errors.type`\n9. `en.json_schemer.errors.*`\n\n## OpenAPI\n\n```ruby\ndocument = JSONSchemer.openapi({\n  'openapi' =\u003e '3.1.0',\n  'info' =\u003e {\n    'title' =\u003e 'example'\n  },\n  'components' =\u003e {\n    'schemas' =\u003e {\n      'example' =\u003e {\n        'type' =\u003e 'integer'\n      }\n    }\n  }\n})\n\n# document validation using meta schema\n\ndocument.valid?\n# =\u003e false\n\ndocument.validate.to_a\n# =\u003e [{\"data\"=\u003e{\"title\"=\u003e\"example\"},\n#      \"data_pointer\"=\u003e\"/info\",\n#      \"schema\"=\u003e{...info schema},\n#      \"schema_pointer\"=\u003e\"/$defs/info\",\n#      \"root_schema\"=\u003e{...meta schema},\n#      \"type\"=\u003e\"required\",\n#      \"details\"=\u003e{\"missing_keys\"=\u003e[\"version\"]}},\n#     ...]\n\n# data validation using schema by name (in `components/schemas`)\n\ndocument.schema('example').valid?(1)\n# =\u003e true\n\ndocument.schema('example').valid?('one')\n# =\u003e false\n\n# data validation using schema by ref\n\ndocument.ref('#/components/schemas/example').valid?(1)\n# =\u003e true\n\ndocument.ref('#/components/schemas/example').valid?('one')\n# =\u003e false\n```\n\n## CLI\n\nThe `json_schemer` executable takes a JSON schema file as the first argument followed by one or more JSON data files to validate. If there are any validation errors, it outputs them and returns an error code.\n\nValidation errors are output as single-line JSON objects. The `--errors` option can be used to limit the number of errors returned or prevent output entirely (and fail fast).\n\nThe schema or data can also be read from stdin using `-`.\n\n```\n% json_schemer --help\nUsage:\n  json_schemer [options] \u003cschema\u003e \u003cdata\u003e...\n  json_schemer [options] \u003cschema\u003e -\n  json_schemer [options] - \u003cdata\u003e...\n  json_schemer -h | --help\n  json_schemer --version\n\nOptions:\n  -e, --errors MAX                 Maximum number of errors to output\n                                   Use \"0\" to validate with no output\n  -h, --help                       Show help\n  -v, --version                    Show version\n```\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\n## Build Status\n\n![CI](https://github.com/davishmcclurg/json_schemer/actions/workflows/ci.yml/badge.svg)\n![JSON Schema Versions](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fruby-json_schemer%2Fsupported_versions.json)\u003cbr\u003e\n![Draft 2020-12](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fruby-json_schemer%2Fcompliance%2Fdraft2020-12.json)\n![Draft 2019-09](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fruby-json_schemer%2Fcompliance%2Fdraft2019-09.json)\n![Draft 7](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fruby-json_schemer%2Fcompliance%2Fdraft7.json)\n![Draft 6](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fruby-json_schemer%2Fcompliance%2Fdraft6.json)\n![Draft 4](https://img.shields.io/endpoint?url=https%3A%2F%2Fbowtie.report%2Fbadges%2Fruby-json_schemer%2Fcompliance%2Fdraft4.json)\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/davishmcclurg/json_schemer.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavishmcclurg%2Fjson_schemer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavishmcclurg%2Fjson_schemer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavishmcclurg%2Fjson_schemer/lists"}