{"id":13726753,"url":"https://github.com/mirego/activerecord_json_validator","last_synced_at":"2025-04-12T22:16:51.047Z","repository":{"id":11871949,"uuid":"14432236","full_name":"mirego/activerecord_json_validator","owner":"mirego","description":"🔩 ActiveRecord::JSONValidator makes it easy to validate JSON attributes against a JSON schema.","archived":false,"fork":false,"pushed_at":"2025-01-23T01:13:37.000Z","size":119,"stargazers_count":415,"open_issues_count":12,"forks_count":64,"subscribers_count":50,"default_branch":"master","last_synced_at":"2025-04-12T22:16:46.425Z","etag":null,"topics":["activemodel","activerecord","json-schema"],"latest_commit_sha":null,"homepage":"https://open.mirego.com","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mirego.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","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":"2013-11-15T18:46:57.000Z","updated_at":"2025-02-14T15:51:39.000Z","dependencies_parsed_at":"2024-04-03T18:50:46.407Z","dependency_job_id":"a6206c09-c5d9-4459-88ae-b19ac139ce4d","html_url":"https://github.com/mirego/activerecord_json_validator","commit_stats":{"total_commits":93,"total_committers":13,"mean_commits":7.153846153846154,"dds":"0.26881720430107525","last_synced_commit":"0af34f5e27c2b36a4501018581520c2b9742bf25"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirego%2Factiverecord_json_validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirego%2Factiverecord_json_validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirego%2Factiverecord_json_validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mirego%2Factiverecord_json_validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mirego","download_url":"https://codeload.github.com/mirego/activerecord_json_validator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248637787,"owners_count":21137538,"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":["activemodel","activerecord","json-schema"],"created_at":"2024-08-03T01:03:19.332Z","updated_at":"2025-04-12T22:16:51.024Z","avatar_url":"https://github.com/mirego.png","language":"Ruby","readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/mirego/activerecord_json_validator\"\u003e\n    \u003cimg src=\"https://user-images.githubusercontent.com/11348/126779905-3468eb15-d554-46d5-925b-235f68169d86.png\" alt=\"\" /\u003e\n  \u003c/a\u003e\n  \u003cbr /\u003e\n  \u003ccode\u003eActiveRecord::JSONValidator\u003c/code\u003e makes it easy to validate\u003cbr /\u003e JSON attributes against a \u003ca href=\"https://json-schema.org/\"\u003eJSON schema\u003c/a\u003e.\n  \u003cbr /\u003e\u003cbr /\u003e\n  \u003ca href=\"https://rubygems.org/gems/activerecord_json_validator\"\u003e\u003cimg src=\"https://img.shields.io/gem/v/activerecord_json_validator.svg\" /\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/mirego/activerecord_json_validator/actions/workflows/ci.yaml\"\u003e\u003cimg src=\"https://github.com/mirego/activerecord_json_validator/actions/workflows/ci.yaml/badge.svg\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'activerecord_json_validator', '~\u003e 3.1.0'\n```\n\n## Usage\n\n### JSON Schema\n\nSchemas should be a JSON file\n\n```json\n{\n  \"type\": \"object\",\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"properties\": {\n    \"city\": { \"type\": \"string\" },\n    \"country\": { \"type\": \"string\" }\n  },\n  \"required\": [\"country\"]\n}\n```\n\n### Ruby\n\n```ruby\ncreate_table \"users\" do |t|\n  t.string \"name\"\n  t.json \"profile\" # First-class JSON with PostgreSQL, yo.\nend\n\nclass User \u003c ActiveRecord::Base\n  # Constants\n  PROFILE_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json')\n\n  # Validations\n  validates :name, presence: true\n  validates :profile, presence: true, json: { schema: PROFILE_JSON_SCHEMA }\nend\n\nuser = User.new(name: 'Samuel Garneau', profile: { city: 'Quebec City' })\nuser.valid? # =\u003e false\n\nuser = User.new(name: 'Samuel Garneau', profile: { city: 'Quebec City', country: 'Canada' })\nuser.valid? # =\u003e true\n\nuser = User.new(name: 'Samuel Garneau', profile: '{invalid JSON\":}')\nuser.valid? # =\u003e false\nuser.profile_invalid_json # =\u003e '{invalid JSON\":}'\n```\n\n#### Options\n\n| Option     | Description                                                                                                                    |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------ |\n| `:schema`  | The JSON schema to validate the data against (see **Schema** section)                                                          |\n| `:value`   | The actual value to use when validating (see **Value** section)                                                                |\n| `:message` | The ActiveRecord message added to the record errors (see **Message** section)                                                  |\n| `:options` | A `Hash` of [`json_schemer`](https://github.com/davishmcclurg/json_schemer#options)-supported options to pass to the validator |\n\n##### Schema\n\n`ActiveRecord::JSONValidator` uses the [json_schemer](https://github.com/davishmcclurg/json_schemer) gem to validate the JSON\ndata against a JSON schema.\n\nAdditionally, you can use a `Symbol` or a `Proc`. Both will be executed in the\ncontext of the validated record (`Symbol` will be sent as a method and the\n`Proc` will be `instance_exec`ed)\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  # Constants\n  PROFILE_REGULAR_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema')\n  PROFILE_ADMIN_JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile_admin.json_schema')\n\n  # Validations\n  validates :profile, presence: true, json: { schema: lambda { dynamic_profile_schema } } # `schema: :dynamic_profile_schema` would also work\n\n  def dynamic_profile_schema\n    admin? ? PROFILE_ADMIN_JSON_SCHEMA : PROFILE_REGULAR_JSON_SCHEMA\n  end\nend\n```\n\nThe schema is passed to the `JSONSchemer.schema` function, so it can be anything supported by it:\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  # Constants\n  JSON_SCHEMA = Rails.root.join('config', 'schemas', 'profile.json_schema')\n  # JSON_SCHEMA = { 'type' =\u003e 'object', 'properties' =\u003e { 'foo' =\u003e { 'type' =\u003e 'integer', 'minimum' =\u003e 3 } } }\n  # JSON_SCHEMA = '{\"type\":\"object\",\"properties\":{\"foo\":{\"type\":\"integer\",\"minimum\":3}}}'\n\n  # Validations\n  validates :profile, presence: true, json: { schema: JSON_SCHEMA }\nend\n```\n\n##### Value\n\nBy default, the validator will use the “getter” method to the fetch attribute\nvalue and validate the schema against it.\n\n```ruby\n# Will validate `self.foo`\nvalidates :foo, json: { schema: SCHEMA }\n```\n\nBut you can change this behavior if the getter method doesn’t return raw JSON data (a `Hash`):\n\n```ruby\n# Will validate `self[:foo]`\nvalidates :foo, json: { schema: SCHEMA, value: -\u003e(record, _, _) { record[:foo] } }\n```\n\nYou could also implement a “raw getter” if you want to avoid the `value` option:\n\n```ruby\n# Will validate `self[:foo]`\nvalidates :raw_foo, json: { schema: SCHEMA }\n\ndef raw_foo\n  self[:foo]\nend\n```\n\n##### Message\n\nLike any other ActiveModel validation, you can specify either a `Symbol` or\n`String` value for the `:message` option. The default value is `:invalid_json`.\n\nHowever, you can also specify a `Proc` that returns an array of errors. The\n`Proc` will be called with a single argument — an array of errors returned by\nthe JSON schema validator. So, if you’d like to add each of these errors as\na first-level error for the record, you can do this:\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  # Validations\n  validates :profile, presence: true, json: { message: -\u003e(errors) { errors }, schema: 'foo.json_schema' }\nend\n\nuser = User.new.tap(\u0026:valid?)\nuser.errors.full_messages\n# =\u003e [\n#      'The property '#/email' of type Fixnum did not match the following type: string in schema 2d44293f-cd9d-5dca-8a6a-fb9db1de722b#',\n#      'The property '#/full_name' of type Fixnum did not match the following type: string in schema 2d44293f-cd9d-5dca-8a6a-fb9db1de722b#',\n#    ]\n```\n\n## Development\n\nThe tests require a database. We've provided a simple `docker-compose.yml` that will make\nit trivial to run the tests against PostgreSQL. Simply run `docker compose up -d`\nfollowed by `rake spec`. When you're done, run `docker compose down` to stop the database.\n\nIn order to use another database, simply define the `DATABASE_URL` environment variable\nappropriately.\n\n## License\n\n`ActiveRecord::JSONValidator` is © 2013-2025 [Mirego](https://www.mirego.com) and may be freely distributed under the [New BSD license](https://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/activerecord_json_validator/blob/master/LICENSE.md) file.\n\nThe tree logo is based on [this lovely icon](https://thenounproject.com/term/tree/51004/) by [Sara Quintana](https://thenounproject.com/sara.quintana.75), from The Noun Project. Used under a [Creative Commons BY 3.0](https://creativecommons.org/licenses/by/3.0/) license.\n\n## About Mirego\n\n[Mirego](https://www.mirego.com) is a team of passionate people who believe that work is a place where you can innovate and have fun. We're a team of [talented people](https://life.mirego.com) who imagine and build beautiful Web and mobile applications. We come together to share ideas and [change the world](https://www.mirego.org).\n\nWe also [love open-source software](https://open.mirego.com) and we try to give back to the community as much as we can.\n","funding_links":[],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirego%2Factiverecord_json_validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmirego%2Factiverecord_json_validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmirego%2Factiverecord_json_validator/lists"}