{"id":19218105,"url":"https://github.com/salesking/json_schema_tools","last_synced_at":"2026-02-25T22:04:33.800Z","repository":{"id":6126299,"uuid":"7354532","full_name":"salesking/json_schema_tools","owner":"salesking","description":"Tools for building and handling a JSON Schema powered API's","archived":false,"fork":false,"pushed_at":"2016-06-03T15:13:51.000Z","size":210,"stargazers_count":28,"open_issues_count":4,"forks_count":9,"subscribers_count":5,"default_branch":"master","last_synced_at":"2026-01-14T22:00:06.975Z","etag":null,"topics":["json-schema","ruby"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salesking.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-12-28T13:14:08.000Z","updated_at":"2025-12-01T22:41:22.000Z","dependencies_parsed_at":"2022-09-13T21:50:51.708Z","dependency_job_id":null,"html_url":"https://github.com/salesking/json_schema_tools","commit_stats":null,"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/salesking/json_schema_tools","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesking%2Fjson_schema_tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesking%2Fjson_schema_tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesking%2Fjson_schema_tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesking%2Fjson_schema_tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salesking","download_url":"https://codeload.github.com/salesking/json_schema_tools/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesking%2Fjson_schema_tools/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28618297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T22:24:05.405Z","status":"ssl_error","status_checked_at":"2026-01-20T22:20:31.342Z","response_time":117,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","ruby"],"created_at":"2024-11-09T14:25:17.102Z","updated_at":"2026-02-25T22:04:33.785Z","avatar_url":"https://github.com/salesking.png","language":"Ruby","readme":"# JSON Schema Tools\n\n[![Build Status](https://travis-ci.org/salesking/json_schema_tools.png?branch=master)](https://travis-ci.org/salesking/json_schema_tools)\n\nToolbox to work with JSON Schema in Ruby:\n\n* blow up classes from schema\n* object.as_schema_json conversion\n* object.valid? validations with object.errors\n\nSimply use full blown classes or customize the bits and pieces:\n\n* add schema properties to an existing class\n* add validations to an existing class\n* clean parameters e.g. in an api controller\n* customize json output, object namespaces, used schema\n\n## Usage\n\nHook the gem into your app\n\n    gem 'json_schema_tools'\n\nQuickstart assuming you have schema definitions [like those](https://github.com/salesking/sk_api_schema/tree/develop/json/v2.0) in place.\n\n```ruby\n# add schema directory to the search path\nSchemaTools.schema_path = '/path/to/json-schema-files'\n# blow up classes for each schema file\nSchemaTools::KlassFactory.build\n\n# init with params (assumes a contact.json definition)\ncontact = Contact.new first_name: 'Barry', last_name: 'Cade'\n# use setters/getters\ncontact.first_name = 'Ahr'\n# validations derived from property definitions\ncontact.valid?\ncontact.errors.full_messages\n```\n\n## Schema handling\n\nBefore the fun begins, with any of the tools, one or multiple JSON schema(files)\nmust be available. A schema is converted into a ruby hash and for convenience is\ncached into a registry (global or per reader object). Globals are initialized\nonce e.g on program start. A reader object allows to handle schemata in dynamic\nways.\n\nWhen using the global SchemaTools::Reader simply provide a base path to the\nschema files and you are done.\n\n```ruby\nSchemaTools.schema_path = '/path/to/schema-json-files'\n```\n\nRead a single schema:\n\n```ruby\nschema = SchemaTools::Reader.read :client\n```\n\nRead a schema from an existing Ruby hash:\n\n```ruby\nschema = SchemaTools::Reader.read :client, { ... }\n```\n\nRead multiple schemas, all *.json files in schema path\n\n```ruby\nschemata = SchemaTools::Reader.read_all\n```\n\nSchemata are cached in registry\n\n```ruby\nSchemaTools::Reader.registry[:client]\n```\n\nRead files from a custom path?\n\n```ruby\nschema = SchemaTools::Reader.read :client, 'my/path/to/json-files'\nschemata = SchemaTools::Reader.read_all 'my/path/to/json-files'\n```\n\nDon't like the global path and registry? Create an instance and your save with\na local registry. Use if you have schema with same names but different markup!\n\n```ruby\nreader = SchemaTools::Reader.new\nreader.read :client, 'from/path'\nreader.registry\n```\n\nGet a schema as plain ruby hash with all $refs de-referenced\n\n```ruby\nSchemaTools::Reader.read_all\nclient_schema = SchemaTools::Reader.registry[:client]\nschema_hash = client_schema.to_h\n```\n\n## Object to JSON  - from Schema\n\nAs you probably know such is done e.g in rails via object.as_json. While using\nthis might be simple, it has a damn big drawback: There is no transparent\ncontract about the data-structure, as rails simply uses all fields defined in the\ndatabase(ActiveRecord model). One side-effect: With each migration you are f***ed\n\nA schema provides a public contract about an object definition. Therefore an\ninternal object is converted to it's public(schema) version on delivery(API access).\nFirst the object is converted to a hash containing only the properties(keys)\nfrom its schema definition. Afterwards it is a breeze to convert this hash into\nJSON, with your favorite generator.\n\nFollowing uses client.json schema, detected from peter.class name.underscore =\u003e \"client\",\ninside the global schema_path and adds properties to the clients_hash by simply calling\nclient.send('property-name'):\n\n```ruby\nclass Client \u003c ActiveRecord::Base\n  include SchemaTools::Modules::AsSchema\nend\n\npeter = Client.new name: 'Peter'\npeter.as_schema_json\n#=\u003e \"client\":{\"id\":12, \"name\": \"Peter\", \"email\":\"\",..}\n\npeter.as_hash\n#=\u003e \"client\"=\u003e{\"id\"=\u003e12, \"name\"=\u003e \"Peter\", \"email\"=\u003e\"\",..}\n```\n\nThe AsSchema module is a tiny wrapper for following low level method:\n\n```ruby\npaul = Contact.new name: 'Paul'\ncontact_hash = SchemaTools::Hash.from_schema(paul)\n#=\u003e \"contact\"=\u003e{\"id\"=\u003e12, \"name\"=\u003e \"Paul\",..}\n# to_json is up to you .. or your rails controller\n```\n\n### Customise Output JSON / Hash\n\nFollowing examples show options to customize the resulting json or hash. Of\ncourse they can be combined.\n\nOnly use some fields e.g. to save bandwidth\n\n```ruby\npeter.as_schema_json(fields:['id', 'name'])\n#=\u003e \"client\":{\"id\":12, \"name\": \"Peter\"}\n```\n\nUse a custom schema name e.g. to represent a client as contact. Assumes you also\nhave a schema named contact.json\n\n```ruby\npeter.as_schema_json(class_name: 'contact')\n```\n\nSet a custom schema path\n\n```ruby\npeter.as_schema_json( path: 'path-to/json-files/')\n```\n\nUse your custom reader (preferred over path usage)\n\n```ruby\nreader = SchemaTools::Reader.new\nreader.read_all '/your/custom/path-to-schema-json/\npeter.as_schema_json( reader: reader)\n```\n\nBy default the object hash has the class name (client) and the link-section on\nroot level. This divides the data from the available methods and makes a clear\nstatement about the object type(it's class).\nIf you don't want to traverse that one extra level you can exclude the root\nand move the data one level up. See how class name and links are available\ninline:\n\n```ruby\n\npeter.as_schema_json( exclude_root: true )\n\n#=\u003e {\"id\":12, \"name\"=\u003e \"Peter\",\n#    \"_class_name\":\"client\",\n#    \"_links\":[ .. ] }\n```\n\nOf course the low level hash method also supports all of these options:\n\n```ruby\nclient_hash = SchemaTools::Hash.from_schema(peter, fields:['id', 'name'])\n#=\u003e \"client\"=\u003e{\"id\"=\u003e12, \"name\"=\u003e \"Peter\"}\n```\n\n## Object from JSON\n\nOn any remote site you'll need to instantiate new objects from an incoming json\nstring. Let's assume a contact class which you need for incoming contact json\ndata.  (Example taken from attributes_spec.rb)\n\n```ruby\nSchemaTools.schema_path = '/path/to/schema-json-files-with-contact-def'\nclass Contact\n  include SchemaTools::Modules::Attributes\n  has_schema_attrs :contact\nend\n\njson_str = '{\"id\": \"123456\", \"last_name\": \"Meier\",\"first_name\": \"Peter\"}'\nc = Contact.from_json(json_str)\nc.id #=\u003e \"123456\"\n\n# new object from hash (if your favorite http tool already parsed the json)\nc = Contact.from_hash({\"id\"=\u003e123456, \"last_name\"=\u003e\"Meier\",\"first_name\"=\u003e\"Peter\"})\n\n```\n\n\n## Parameter cleaning\n\nHate people spamming your api with wrong object fields? Use the Cleaner to\ncheck incoming params.\n\nFor example in a client controller\n\n```ruby\ndef create\n  SchemaTools::Cleaner.clean_params!(:client, params[:client])\n  # params[:client] now only has keys defined as writable in client.json schema\n  #..create and save client\nend\n```\n\n## Object attributes from Schema\n\nAdd methods, defined in schema properties, to an existing class.\nVery useful if you are building a API client and don't want to manually add\nmethods to you local classes .. like people NOT using JSON schema\n\n```ruby\nclass Contact\n  include SchemaTools::Modules::Attributes\n  has_schema_attrs :client\nend\n\ncontact = Client.new\ncontact.last_name = 'Rambo'\n# raw access\ncontact.schema_attrs\n# to json\ncontact.as_schema_json\n```\n\n## Classes from Schema - KlassFactory\n\nUse the KlassFactory to directly create classes, with all attributes from a\nschema. Instead of adding attributes to an existing class like in above example.\nThe classes are named after each schema's [name] (in global path).\nSo lets assume you have a 'client.json' schema with a name attribute in it, for\nthe following examples:\n\n```ruby\nSchemaTools::KlassFactory.build\nclient = Client.new first_name: 'Heinz'\nclient.name = 'Schultz'\nclient.valid?\nclient.errors.full_messages\n```\n\nRather like a namespace? Good idea, but don't forget the class or module must\nbe defined.\n\n```ruby\nmodule SalesKing; end\nSchemaTools::KlassFactory.build namespace: SalesKing\ncontact = SalesKing::Contact.new\n```\n\nAdd a custom schema reader most likely useful in conjunction with a custom path\n\n```ruby\nreader = SchemaTools::Reader.new\nSchemaTools::KlassFactory.build reader: reader, path: HappyPdf::Schema.path\n```\n\n## $ref\n\nProvides some basic support for JSON Pointer. JSON Pointer expressions must reference local\nfiles and must contain a fragment identifier, i.e.\n\n     ./some_include.json#properties\n     ./some_include.json#\n\nis a resolvable pointer, while\n\n     http://example.com/public_schema.json\n\nis not.\n\n\n## Real world examples\n\n* [SalesKing json schema](https://github.com/salesking/sk_api_schema)\n* [FidorBank json schema](https://github.com/fidor/fidor_schema)\n* [HappyPdf json schema](https://github.com/happyPDF/happypdf_json_schema)\n* [DocTag ruby gem](https://github.com/docTag/doctag_rb) and [DocTag json-schema](https://github.com/docTag/doctag_json_schema)\n* .. Your UseCase here\n\n## Test\n\nOnly runs on Ruby 1.9+ and by default uses most recent ActiveModel version (\u003e3).\n\n    bundle install\n    rake spec\n\nTesting with different ActiveModel / ActiveSupport Versions:\n\n    RAILS_VERSION=3.1 bundle install\n    rake spec\n    # or if already installed\n    RAILS_VERSION=4 rake spec\n\nThe RAILS_VERSION switch sets the version of the gems in the Gemfile and is only\nuseful in test env.\n\n\n# Credits\n\n* [Andy Nicholson](https://github.com/anicholson)\n\nCopyright 2012-2016, Georg Leciejewski, MIT License\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalesking%2Fjson_schema_tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalesking%2Fjson_schema_tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalesking%2Fjson_schema_tools/lists"}