{"id":41744390,"url":"https://github.com/ro-pi/json-schema-evaluator","last_synced_at":"2026-01-25T00:43:25.629Z","repository":{"id":56937853,"uuid":"389210340","full_name":"ro-pi/json-schema-evaluator","owner":"ro-pi","description":"PHP based JSON Schema Evaluator/Validator","archived":false,"fork":false,"pushed_at":"2024-07-22T21:54:48.000Z","size":320,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-24T15:43:37.765Z","etag":null,"topics":["json","json-schema","json-schema-validation","json-schema-validator","php"],"latest_commit_sha":null,"homepage":"","language":"PHP","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/ro-pi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2021-07-24T22:04:27.000Z","updated_at":"2024-07-22T21:52:15.000Z","dependencies_parsed_at":"2023-12-01T01:33:48.197Z","dependency_job_id":"95fc559e-7c90-4e5a-860e-832e1acc8885","html_url":"https://github.com/ro-pi/json-schema-evaluator","commit_stats":{"total_commits":65,"total_committers":3,"mean_commits":"21.666666666666668","dds":0.2153846153846154,"last_synced_commit":"56a7d329f28497d5700743f854c556cbb6c4ec76"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/ro-pi/json-schema-evaluator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ro-pi%2Fjson-schema-evaluator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ro-pi%2Fjson-schema-evaluator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ro-pi%2Fjson-schema-evaluator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ro-pi%2Fjson-schema-evaluator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ro-pi","download_url":"https://codeload.github.com/ro-pi/json-schema-evaluator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ro-pi%2Fjson-schema-evaluator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28740196,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-24T22:12:27.248Z","status":"ssl_error","status_checked_at":"2026-01-24T22:12:10.529Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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","json-schema","json-schema-validation","json-schema-validator","php"],"created_at":"2026-01-25T00:43:24.991Z","updated_at":"2026-01-25T00:43:25.619Z","avatar_url":"https://github.com/ro-pi.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A modern JSON Schema evaluator for PHP\n\nThis library is a PHP based implementation for evaluating and validating [JSON Schemas](https://json-schema.org/).\nThe library can be easily extended with your own keywords and drafts.\n\n## Requirements\n* PHP \u003e= 8.1\n* ext-bcmath\n* ext-mbstring\n* ext-fileinfo\n\n## Table of contents\n* [Installation](#installation)\n* [Supported drafts](#supported-drafts)\n* [Basic examples](#basic-examples)\n  * [Basic usage](#basic-usage)\n  * [Read individual error results](#read-individual-error-results)\n  * [Formatting results](#formatting-results)\n* [Mutations](#mutations)\n  * [Default values](#default-values)\n  * [Content decoding](#content-decoding)\n* [Advanced examples](#advanced-examples)\n  * [Assert content media type](#assert-content-media-type)\n  * [Assert format](#assert-format)\n  * [Short-circuiting](#short-circuiting)\n  * [Big numbers](#big-numbers-interpret-numeric-strings-as-numbers)\n  * [Custom keywords](#custom-keywords)\n\n## Installation\nThe library can be installed from a command line interface by using [composer](https://getcomposer.org/).\n\n## Supported drafts\n\n### Draft 2020-12 ([Core](https://json-schema.org/draft/2020-12/json-schema-core.html) and [Validation](https://json-schema.org/draft/2020-12/json-schema-validation.html))\nPasses all tests of [official JSON schema test suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite) except the following optional tests:\n* [optional/refOfUnknownKeyword.json](https://github.com/json-schema-org/JSON-Schema-Test-Suite/blob/master/tests/draft2020-12/optional/refOfUnknownKeyword.json):\n  This means that you cannot use the \u003cb\u003e$ref\u003c/b\u003e keyword to reference schemas that are located inside unknown keywords.\n* [optional/ecmascript-regex.json](https://github.com/json-schema-org/JSON-Schema-Test-Suite/blob/master/tests/draft2020-12/optional/ecmascript-regex.json):\n  This means that the specifics of Ecmascript regular expressions are not respected. Instead, regular expressions are evaluated as PERL regular expressions.\n\n```\ncomposer require ropi/json-schema-evaluator\n```\n## Basic examples\n### Basic usage\n```php\n$schema = json_decode('{\n    \"type\": \"string\",\n    \"maxLength\": 5\n}');\n\n$evaluator = new \\Ropi\\JsonSchemaEvaluator\\JsonSchemaEvaluator();\n\n// Each JSON Schema must be statically analyzed once.\n$staticEvaluationContext = $evaluator-\u003eevaluateStatic($schema, new \\Ropi\\JsonSchemaEvaluator\\EvaluationConfig\\StaticEvaluationConfig(\n    defaultDraft: new \\Ropi\\JsonSchemaEvaluator\\Draft\\Draft202012()\n));\n\n$instance1 = \"hello\";\n$evaluator-\u003eevaluate($instance1, $staticEvaluationContext); // Returns true\n\n$instance2 = \"helloworld\";\n$evaluator-\u003eevaluate($instance2, $staticEvaluationContext); // Returns false\n```\n\n### Read individual error results\n```php\n$valid = $evaluator-\u003eevaluate(\n    instance: $instance2,\n    staticEvaluationContext: $staticEvaluationContext,\n    results: $results\n);\n\nforeach ($results as $result) {\n    /** @var $result \\Ropi\\JsonSchemaEvaluator\\EvaluationContext\\RuntimeEvaluationResult */\n    if ($result-\u003etype === 'error') {\n        echo \"Error keyword location: '{$result-\u003ekeywordLocation}'\\n\";\n        echo \"Error instance location: '{$result-\u003einstanceLocation}'\\n\";\n        echo \"Error message: {$result-\u003eerror}\\n\";\n    }\n}\n```\nOutput of above example:\n```\nError keyword location: '/maxLength'\nError instance location: ''\nError message: At most 5 characters are allowed, but there are 10.\n```\n### Formatting results\nIn the following example, the results are formatted as [Basic Output Structure](https://json-schema.org/draft/2020-12/json-schema-core#name-basic). In addition, only the [Flag Output Structure](https://json-schema.org/draft/2020-12/json-schema-core#name-flag) is also currently supported.\n```php\n$formattedResults = (new \\Ropi\\JsonSchemaEvaluator\\Output\\BasicOutput($valid, $results))-\u003eformat();\necho json_encode($formattedResults, JSON_PRETTY_PRINT);\n```\nOutput of above example: \n```json\n{\n  \"valid\": false,\n  \"errors\": [\n    {\n      \"type\": \"annotation\",\n      \"valid\": true,\n      \"keywordLocation\": \"\\/type\",\n      \"instanceLocation\": \"\",\n      \"keywordName\": \"type\",\n      \"error\": \"\",\n      \"errorMeta\": null,\n      \"annotation\": [\n        \"string\"\n      ]\n    },\n    {\n      \"type\": \"error\",\n      \"valid\": false,\n      \"keywordLocation\": \"\\/maxLength\",\n      \"instanceLocation\": \"\",\n      \"keywordName\": \"maxLength\",\n      \"error\": \"At most 5 characters are allowed, but there are 10.\",\n      \"errorMeta\": null\n    }\n  ]\n}\n```\n## Mutations\n### Default values\nIf a default value is defined with the [default keyword](https://json-schema.org/draft/2020-12/json-schema-validation#name-default), it can be automatically applied during evaluation.\n```php\n$schema = json_decode('{\n    \"type\": \"object\",\n    \"required\": [\"lastname\"],\n    \"properties\": {\n        \"firstname\": {\n            \"default\": \"n/a\"\n        }\n    }\n}');\n\n$evaluator = new \\Ropi\\JsonSchemaEvaluator\\JsonSchemaEvaluator();\n\n$staticEvaluationContext = $evaluator-\u003eevaluateStatic($schema, new \\Ropi\\JsonSchemaEvaluator\\EvaluationConfig\\StaticEvaluationConfig(\n    defaultDraft: new \\Ropi\\JsonSchemaEvaluator\\Draft\\Draft202012(\n        evaluateMutations: true\n    )\n));\n\n$instance = (object) [\n    'lastname' =\u003e 'Gauss'\n];\n\n$evaluator-\u003eevaluate($instance, $staticEvaluationContext);\n\necho $instance-\u003efirstname; // Prints \"n/a\"\n```\n\n### Content decoding\nIf encoded content is defined with the [contentEncoding keyword](https://json-schema.org/draft/2020-12/json-schema-validation#name-contentencoding), it can be automatically decoded during evaluation.\n```php\n$schema = json_decode('{\n    \"contentMediaType\": \"application/json\",\n    \"contentEncoding\": \"base64\"\n}');\n\n$evaluator = new \\Ropi\\JsonSchemaEvaluator\\JsonSchemaEvaluator();\n\n$staticEvaluationContext = $evaluator-\u003eevaluateStatic($schema, new \\Ropi\\JsonSchemaEvaluator\\EvaluationConfig\\StaticEvaluationConfig(\n    defaultDraft: new \\Ropi\\JsonSchemaEvaluator\\Draft\\Draft202012(\n        evaluateMutations: true\n    )\n));\n\n$instance = 'eyJmb28iOiAiYmFyIn0K'; // Base64 encoded JSON '{\"foo\": \"bar\"}'\n\n$evaluator-\u003eevaluate($instance, $staticEvaluationContext); // Returns true\n\necho $instance; // Prints '{\"foo\": \"bar\"}'\n```\n## Advanced examples\n### Assert content media type\nIf content media type is defined with the [contentMediaType keyword](https://json-schema.org/draft/2020-12/json-schema-validation#name-contentmediatype), it can be respected during evaluation.\n```php\n$schema = json_decode('{\n    \"contentMediaType\": \"application/json\"\n}');\n\n$evaluator = new \\Ropi\\JsonSchemaEvaluator\\JsonSchemaEvaluator();\n\n$staticEvaluationContext = $evaluator-\u003eevaluateStatic($schema, new \\Ropi\\JsonSchemaEvaluator\\EvaluationConfig\\StaticEvaluationConfig(\n    defaultDraft: new \\Ropi\\JsonSchemaEvaluator\\Draft\\Draft202012(\n        assertContentMediaTypeEncoding: true\n    )\n));\n\n$instance = '{\"foo\": \"bar\"}';\n$evaluator-\u003eevaluate($instance, $staticEvaluationContext); // Returns true\n\n$instance2 = 'invalidJSON';\n$evaluator-\u003eevaluate($instance2, $staticEvaluationContext); // Returns false\n```\n\n### Assert format\nIf format is defined with the [format keyword](https://json-schema.org/draft/2020-12/json-schema-validation#name-format-annotation-vocabular), it can be respected during evaluation. \n```php\n$schema = json_decode('{\n    \"format\": \"email\"\n}');\n\n$evaluator = new \\Ropi\\JsonSchemaEvaluator\\JsonSchemaEvaluator();\n\n$staticEvaluationContext = $evaluator-\u003eevaluateStatic($schema, new \\Ropi\\JsonSchemaEvaluator\\EvaluationConfig\\StaticEvaluationConfig(\n    defaultDraft: new \\Ropi\\JsonSchemaEvaluator\\Draft\\Draft202012(\n        assertFormat: true\n    )\n));\n\n$instance = 'test@example.com';\n$evaluator-\u003eevaluate($instance, $staticEvaluationContext, $runtimeEvaluationConfig); // Returns true\n\n$instance2 = 'invalidEmail';\n$evaluator-\u003eevaluate($instance2, $staticEvaluationContext, $runtimeEvaluationConfig); // Returns false\n```\n\n### Short-circuiting\nBy default, all keywords are evaluated, even if the first keyword validation fails.\nIf short circuiting is activated, the evaluation stops at the first negative validation result.\n```php\n$config = new \\Ropi\\JsonSchemaEvaluator\\EvaluationConfig\\StaticEvaluationConfig(\n    defaultDraft: new \\Ropi\\JsonSchemaEvaluator\\Draft\\Draft202012(\n        shortCircuit: true\n    )\n);\n```\n\n### Big numbers (interpret numeric strings as numbers)\n```php\n$schema = json_decode('{\n    \"type\": \"integer\"\n}');\n\n$evaluator = new \\Ropi\\JsonSchemaEvaluator\\JsonSchemaEvaluator();\n\n$staticEvaluationContext = $evaluator-\u003eevaluateStatic($schema, new \\Ropi\\JsonSchemaEvaluator\\EvaluationConfig\\StaticEvaluationConfig(\n    defaultDraft: new \\Ropi\\JsonSchemaEvaluator\\Draft\\Draft202012(\n        acceptNumericStrings: true\n    )\n));\n\n$instance = json_decode('6565650699413464649797946464646464649797979', false, 512, JSON_BIGINT_AS_STRING);\n$evaluator-\u003eevaluate($instance, $staticEvaluationContext); // Returns true\n```\n\n### Custom keywords\nIt is possible to add custom keywords to a draft.\\\nThe following example shows how to implement a keyword where the instance must match a specific md5 hash.\n```php\n$schema = json_decode('{\n    \"md5Hash\": \"098f6bcd4621d373cade4e832627b4f6\"\n}');\n\nclass Md5HashKeyword extends \\Ropi\\JsonSchemaEvaluator\\Keyword\\AbstractKeyword implements \\Ropi\\JsonSchemaEvaluator\\Keyword\\RuntimeKeywordInterface\n{\n    public function getName() : string\n    {\n        return \"md5Hash\";\n    }\n\n    public function evaluate(mixed $keywordValue, \\Ropi\\JsonSchemaEvaluator\\EvaluationContext\\RuntimeEvaluationContext $context): ?\\Ropi\\JsonSchemaEvaluator\\EvaluationContext\\RuntimeEvaluationResult\n    {\n        $instance = $context-\u003egetCurrentInstance();\n        if (!is_string($instance)) {\n            // Ignore keyword, because instance is not a string\n            return null;\n        }\n\n        $result = $context-\u003ecreateResultForKeyword($this, $keywordValue);\n\n        if (md5($instance) !== $keywordValue) {\n            $result-\u003einvalidate('MD5 hash of \"' . $instance . '\" does not match ' . $keywordValue);\n        }\n\n        return $result;\n    }\n}\n\n$draft = new \\Ropi\\JsonSchemaEvaluator\\Draft\\Draft202012();\n$draft-\u003eregisterKeyword(new Md5HashKeyword(), 'https://example.tld/draft/2022-03/vocab/md5'); // Register keyword with custom vocabulary\n\n$evaluator = new \\Ropi\\JsonSchemaEvaluator\\JsonSchemaEvaluator();\n\n$staticEvaluationContext = $evaluator-\u003eevaluateStatic($schema, new \\Ropi\\JsonSchemaEvaluator\\EvaluationConfig\\StaticEvaluationConfig(\n    defaultDraft: $draft\n));\n\n$instance = 'test';\n$evaluator-\u003eevaluate($instance, $staticEvaluationContext); // Returns true, because md5 hash matches\n\n$instance = 'hello';\n$evaluator-\u003eevaluate($instance, $staticEvaluationContext); // Returns false, because md5 hash does not match\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fro-pi%2Fjson-schema-evaluator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fro-pi%2Fjson-schema-evaluator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fro-pi%2Fjson-schema-evaluator/lists"}