{"id":13784016,"url":"https://github.com/karenetheridge/JSON-Schema-Modern","last_synced_at":"2025-05-11T19:32:01.217Z","repository":{"id":37973800,"uuid":"260538304","full_name":"karenetheridge/JSON-Schema-Modern","owner":"karenetheridge","description":"Validate data against a schema using a JSON Schema","archived":false,"fork":false,"pushed_at":"2024-10-20T22:34:47.000Z","size":10863,"stargazers_count":11,"open_issues_count":32,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-10-21T02:46:09.509Z","etag":null,"topics":["json-schema"],"latest_commit_sha":null,"homepage":"https://metacpan.org/release/JSON-Schema-Modern/","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karenetheridge.png","metadata":{"files":{"readme":"README.pod","changelog":"Changes","contributing":"CONTRIBUTING","funding":null,"license":null,"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":"2020-05-01T19:09:39.000Z","updated_at":"2024-10-20T22:34:50.000Z","dependencies_parsed_at":"2023-11-13T01:37:29.585Z","dependency_job_id":"6dc773b2-62c8-46a4-acb0-8bab52d1a295","html_url":"https://github.com/karenetheridge/JSON-Schema-Modern","commit_stats":{"total_commits":1211,"total_committers":1,"mean_commits":1211.0,"dds":0.0,"last_synced_commit":"c9a971abc59ceb1a2020ab096adcfc8049a964a8"},"previous_names":[],"tags_count":110,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karenetheridge%2FJSON-Schema-Modern","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karenetheridge%2FJSON-Schema-Modern/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karenetheridge%2FJSON-Schema-Modern/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karenetheridge%2FJSON-Schema-Modern/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karenetheridge","download_url":"https://codeload.github.com/karenetheridge/JSON-Schema-Modern/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225086553,"owners_count":17418746,"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"],"created_at":"2024-08-03T19:00:34.388Z","updated_at":"2025-05-11T19:32:01.192Z","avatar_url":"https://github.com/karenetheridge.png","language":"Perl","funding_links":[],"categories":["Who Uses the Test Suite"],"sub_categories":["Perl"],"readme":"=pod\n\n=encoding UTF-8\n\n=for stopwords schema subschema metaschema validator evaluator listref\n\n=head1 NAME\n\nJSON::Schema::Modern - Validate data against a schema using a JSON Schema\n\n=head1 VERSION\n\nversion 0.609\n\n=head1 SYNOPSIS\n\n  use JSON::Schema::Modern;\n\n  $js = JSON::Schema::Modern-\u003enew(\n    specification_version =\u003e 'draft2020-12',\n    output_format =\u003e 'flag',\n    ... # other options\n  );\n  $result = $js-\u003eevaluate($instance_data, $schema_data);\n\n=head1 DESCRIPTION\n\nThis module aims to be a fully-compliant L\u003cJSON Schema|https://json-schema.org/\u003e evaluator and\nvalidator, targeting the currently-latest\nL\u003cDraft 2020-12|https://json-schema.org/specification-links.html#2020-12\u003e\nversion of the specification.\n\n=head1 CONFIGURATION OPTIONS\n\nThese values are all passed as arguments to the constructor.\n\n=head2 specification_version\n\nIndicates which version of the JSON Schema specification is used during evaluation. This value is\noverridden by the value determined from the C\u003c$schema\u003e keyword in the schema used in evaluation\n(when present), or defaults to the latest version (currently C\u003cdraft2020-12\u003e).\n\nThe use of the C\u003c$schema\u003e keyword in your schema is I\u003cHIGHLY\u003e encouraged to ensure continued correct\noperation of your schema. The current default value will not stay the same over time.\n\nMay be one of:\n\n=over 4\n\n=item *\n\nL\u003cC\u003cdraft2020-12\u003e or C\u003c2020-12\u003e|https://json-schema.org/specification-links.html#2020-12\u003e, corresponding to metaschema C\u003chttps://json-schema.org/draft/2020-12/schema\u003e\n\n=item *\n\nL\u003cC\u003cdraft2019-09\u003e or C\u003c2019-09\u003e|https://json-schema.org/specification-links.html#2019-09-formerly-known-as-draft-8\u003e, corresponding to metaschema C\u003chttps://json-schema.org/draft/2019-09/schema\u003e\n\n=item *\n\nL\u003cC\u003cdraft7\u003e or C\u003c7\u003e|https://json-schema.org/specification-links.html#draft-7\u003e, corresponding to metaschema C\u003chttp://json-schema.org/draft-07/schema#\u003e\n\n=item *\n\nL\u003cC\u003cdraft6\u003e or C\u003c6\u003e|https://json-schema.org/specification-links.html#draft-6\u003e, corresponding to metaschema C\u003chttp://json-schema.org/draft-06/schema#\u003e\n\n=item *\n\nL\u003cC\u003cdraft4\u003e or C\u003c4\u003e|https://json-schema.org/specification-links.html#draft-4\u003e, corresponding to metaschema C\u003chttp://json-schema.org/draft-04/schema#\u003e\n\n=back\n\n=head2 output_format\n\nOne of: C\u003cflag\u003e, C\u003cbasic\u003e, C\u003cstrict_basic\u003e, C\u003cterse\u003e. Defaults to C\u003cbasic\u003e.\nC\u003cstrict_basic\u003e can only be used with C\u003cspecification_version = draft2019-09\u003e.\nPassed to L\u003cJSON::Schema::Modern::Result/output_format\u003e.\n\n=head2 short_circuit\n\nWhen true, evaluation will return early in any execution path as soon as the outcome can be\ndetermined, rather than continuing to find all errors or annotations.\nThis option is safe to use in all circumstances, even in the presence of\nC\u003cunevaluatedItems\u003e and C\u003cunevaluatedProperties\u003e keywords: the validation result will not change;\nonly some errors will be omitted from the result.\n\nDefaults to true when C\u003coutput_format\u003e is C\u003cflag\u003e, and false otherwise.\n\n=head2 max_traversal_depth\n\nThe maximum number of levels deep a schema traversal may go, before evaluation is halted. This is to\nprotect against accidental infinite recursion, such as from two subschemas that each reference each\nother, or badly-written schemas that could be optimized. Defaults to 50.\n\n=head2 validate_formats\n\nWhen true, the C\u003cformat\u003e keyword will be treated as an assertion, not merely an annotation. Defaults\nto true when specification_version is draft4, draft6 or draft7, and false for all other versions, but this may change in the future.\n\nNote that the use of a format that does not have a defined handler will B\u003cnot\u003e be interpreted as an\nerror in this mode; instead, the undefined format will simply be ignored. If you instead want this\nto be treated as an evaluation error, you must define a custom schema dialect that uses the\nformat-assertion vocabulary (available in specification version C\u003cdraft2020-12\u003e) and reference it in\nyour schema with the C\u003c$schema\u003e keyword.\n\n=head2 format_validations\n\n=for stopwords subref\n\nAn optional hashref that allows overriding the validation method for formats, or adding new ones.\nOverrides to existing formats (see L\u003c/Format Validation\u003e)\nmust be specified in the form of C\u003c\u003c { $format_name =\u003e $format_sub } \u003e\u003e, where\nthe format sub is a subref that takes one argument and returns a boolean result. New formats must\nbe specified in the form of C\u003c\u003c { $format_name =\u003e { type =\u003e $type, sub =\u003e $format_sub } } \u003e\u003e,\nwhere the type indicates which of the core JSON Schema types (null, object, array, boolean, string,\nnumber, or integer) the instance value must be for the format validation to be considered.\n\n=head2 validate_content_schemas\n\nWhen true, the C\u003ccontentMediaType\u003e and C\u003ccontentSchema\u003e keywords are not treated as pure annotations:\nC\u003ccontentEncoding\u003e (when present) is used to decode the applied data payload and then\nC\u003ccontentMediaType\u003e will be used as the media-type for decoding to produce the data payload which is\nthen applied to the schema in C\u003ccontentSchema\u003e for validation. (Note that treating these keywords as\nanything beyond simple annotations is contrary to the specification, therefore this option defaults\nto false.)\n\nSee L\u003c/add_media_type\u003e and L\u003c/add_encoding\u003e for adding additional type support.\n\n=for stopwords shhh\n\nTechnically only draft4, draft6 and draft7 allow this and drafts 2019-09 and 2020-12 prohibit ever returning the\nsubschema evaluation results together with their parent schema's results, so shhh. I'm trying to get this\nfixed for the next draft.\n\n=head2 collect_annotations\n\nWhen true, annotations are collected from keywords that produce them, when validation succeeds.\nThese annotations are available in the returned result (see L\u003cJSON::Schema::Modern::Result\u003e).\nNot operational when L\u003c/specification_version\u003e is C\u003cdraft4\u003e, C\u003cdraft6\u003e or C\u003cdraft7\u003e.\n\nDefaults to false.\n\n=head2 scalarref_booleans\n\nWhen true, any value that is expected to be a boolean B\u003cin the instance data\u003e may also be expressed\nas the scalar references C\u003c\\0\u003e or C\u003c\\1\u003e (which are serialized as booleans by JSON backends).\n\nDefaults to false.\n\n=head2 stringy_numbers\n\nWhen true, any value that is expected to be a number or integer B\u003cin the instance data\u003e may also be\nexpressed as a string. This applies only to the following keywords:\n\n=over 4\n\n=item *\n\nC\u003ctype\u003e (where both C\u003cstring\u003e and C\u003cnumber\u003e (and possibly C\u003cinteger\u003e) are considered valid)\n\n=item *\n\nC\u003cconst\u003e and C\u003cenum\u003e (where the string C\u003c\"1\"\u003e will match with C\u003c\"const\": 1\u003e)\n\n=item *\n\nC\u003cuniqueItems\u003e (where strings and numbers are compared numerically to each other, if either or both are numeric)\n\n=item *\n\nC\u003cmultipleOf\u003e\n\n=item *\n\nC\u003cmaximum\u003e\n\n=item *\n\nC\u003cexclusiveMaximum\u003e\n\n=item *\n\nC\u003cminimum\u003e\n\n=item *\n\nC\u003cexclusiveMinimum\u003e\n\n=item *\n\nC\u003cformat\u003e (for formats defined to validate numbers)\n\n=back\n\nThis allows you to write a schema like this (which validates a string representing an integer):\n\n  type: string\n  pattern: ^[0-9]$\n  multipleOf: 4\n  minimum: 16\n  maximum: 256\n\nSuch keywords are only applied if the value looks like a number, and do not generate a failure\notherwise. Values are determined to be numbers via L\u003cperlapi/looks_like_number\u003e.\nThis option is only intended to be used for evaluating data from sources that can only be strings,\nsuch as the extracted value of an HTTP header or query parameter.\n\nDefaults to false.\n\n=head2 strict\n\nWhen true, unrecognized keywords are disallowed in schemas (they will cause an immediate abort\nin L\u003c/traverse\u003e or L\u003c/evaluate\u003e).\n\nDefaults to false.\n\n=head1 METHODS\n\n=for Pod::Coverage BUILDARGS FREEZE THAW\nCACHED_METASCHEMAS METASCHEMA_URIS SPECIFICATION_VERSIONS_SUPPORTED SPECIFICATION_VERSION_DEFAULT\n\n=head2 evaluate_json_string\n\n  $result = $js-\u003eevaluate_json_string($data_as_json_string, $schema);\n  $result = $js-\u003eevaluate_json_string($data_as_json_string, $schema, { collect_annotations =\u003e 1 });\n\nEvaluates the provided instance data against the known schema document.\n\nThe data is in the form of a JSON-encoded string (in accordance with\nL\u003cRFC8259|https://datatracker.ietf.org/doc/html/rfc8259\u003e). B\u003cThe string is expected to be UTF-8 encoded.\u003e\n\nThe schema must be in one of these forms:\n\n=over 4\n\n=item *\n\na Perl data structure, such as what is returned from a JSON decode operation,\n\n=item *\n\na L\u003cJSON::Schema::Modern::Document\u003e object,\n\n=item *\n\nor a URI string indicating the location where such a schema is located.\n\n=back\n\nOptionally, a hashref can be passed as a third parameter which allows changing the values of the\nL\u003c/short_circuit\u003e, L\u003c/collect_annotations\u003e, L\u003c/scalarref_booleans\u003e,\nL\u003c/stringy_numbers\u003e, L\u003c/strict\u003e, L\u003c/validate_formats\u003e, and/or L\u003c/validate_content_schemas\u003e\nsettings for just this evaluation call.\n\nYou can also pass use these keys to alter behaviour (these are generally only used by custom validation\napplications that contain embedded JSON Schemas):\n\n=over 4\n\n=item *\n\nC\u003cdata_path\u003e: adjusts the effective path of the data instance as of the start of evaluation\n\n=item *\n\nC\u003ctraversed_schema_path\u003e: adjusts the accumulated path as of the start of evaluation (or last C\u003c$id\u003e or C\u003c$ref\u003e)\n\n=item *\n\nC\u003cinitial_schema_uri\u003e: adjusts the recorded absolute keyword location as of the start of evaluation\n\n=item *\n\nC\u003ceffective_base_uri\u003e: locations in errors and annotations are resolved against this URI (only useful when providing an inline schema that does not declare an absolute base URI for itself)\n\n=back\n\nThe return value is a L\u003cJSON::Schema::Modern::Result\u003e object, which can also be used as a boolean.\n\n=head2 evaluate\n\n  $result = $js-\u003eevaluate($instance_data, $schema);\n  $result = $js-\u003eevaluate($instance_data, $schema, { short_circuit =\u003e 0 });\n\nEvaluates the provided instance data against the known schema document.\n\nThe data is in the form of an unblessed nested Perl data structure representing any type that JSON\nallows: null, boolean, string, number, object, array. (See L\u003c/Types\u003e below.)\n\nThe schema must be in one of these forms:\n\n=over 4\n\n=item *\n\na Perl data structure, such as what is returned from a JSON decode operation,\n\n=item *\n\na L\u003cJSON::Schema::Modern::Document\u003e object,\n\n=item *\n\nor a URI string indicating the location where such a schema is located.\n\n=back\n\nOptionally, a hashref can be passed as a third parameter which allows changing the values of the\nL\u003c/short_circuit\u003e, L\u003c/collect_annotations\u003e, L\u003c/scalarref_booleans\u003e,\nL\u003c/stringy_numbers\u003e, L\u003c/strict\u003e, L\u003c/validate_formats\u003e, and/or L\u003c/validate_content_schemas\u003e\nsettings for just this evaluation call.\n\nYou can also pass use these keys to alter behaviour (these are generally only used by custom validation\napplications that contain embedded JSON Schemas):\n\n=over 4\n\n=item *\n\nC\u003cdata_path\u003e: adjusts the effective path of the data instance as of the start of evaluation\n\n=item *\n\nC\u003ctraversed_schema_path\u003e: adjusts the accumulated path as of the start of evaluation (or last C\u003c$id\u003e or C\u003c$ref\u003e)\n\n=item *\n\nC\u003ceffective_base_uri\u003e: locations in errors and annotations are resolved against this URI (only useful when providing an inline schema that does not declare an absolute base URI for itself)\n\n=back\n\nYou can pass a series of callback subs to this method corresponding to keywords, which is useful for\nidentifying various data that are not exposed by annotations.\nThis feature is highly experimental and may change in the future.\n\nFor example, to find the locations where all C\u003c$ref\u003e keywords are applied B\u003csuccessfully\u003e:\n\n  my @used_ref_at;\n  $js-\u003eevaluate($data, $schema_or_uri, {\n    callbacks =\u003e {\n      '$ref' =\u003e sub ($data, $schema, $state) {\n        push @used_ref_at, $state-\u003e{data_path};\n      }\n    },\n  });\n\nThe return value is a L\u003cJSON::Schema::Modern::Result\u003e object, which can also be used as a boolean.\nCallbacks are not compatible with L\u003c/short_circuit\u003e mode.\n\n=head2 validate_schema\n\n  $result = $js-\u003evalidate_schema($schema);\n  $result = $js-\u003evalidate_schema($schema, $config_override);\n\nEvaluates the provided schema as instance data against its metaschema. Accepts C\u003c$schema\u003e and\nC\u003c$config_override\u003e parameters in the same form as L\u003c/evaluate\u003e.\n\n=head2 traverse\n\n  $result = $js-\u003etraverse($schema);\n  $result = $js-\u003etraverse($schema, { initial_schema_uri =\u003e 'http://example.com' });\n\nTraverses the provided schema without evaluating it against any instance data. Returns the\ninternal state object accumulated during the traversal, including any identifiers found therein, and\nany errors found during parsing. For internal purposes only.\n\nOptionally, a hashref can be passed as a second parameter which alters some\nbehaviour (these are generally only used by custom validation\napplications that contain embedded JSON Schemas):\n\n=over 4\n\n=item *\n\nC\u003ctraversed_schema_path\u003e: adjusts the accumulated path as of the start of evaluation (or last C\u003c$id\u003e or C\u003c$ref\u003e)\n\n=item *\n\nC\u003cinitial_schema_uri\u003e: adjusts the absolute keyword location as of the start of evaluation\n\n=item *\n\nC\u003cmetaschema_uri\u003e: use the indicated URI as the metaschema\n\n=back\n\nYou can pass a series of callback subs to this method corresponding to keywords, which is useful for\nextracting data from within schemas and skipping properties that may look like keywords but actually\nare not (for example C\u003c{\"const\": {\"$ref\": \"this is not actually a $ref\"}}\u003e). This feature is highly\nexperimental and is highly likely to change in the future.\n\nFor example, to find the resolved targets of all C\u003c$ref\u003e keywords in a schema document:\n\n  my @refs;\n  JSON::Schema::Modern-\u003enew-\u003etraverse($schema, {\n    callbacks =\u003e {\n      '$ref' =\u003e sub ($schema, $state) {\n        push @refs, Mojo::URL-\u003enew($schema-\u003e{'$ref'})\n          -\u003eto_abs(JSON::Schema::Modern::Utilities::canonical_uri($state));\n      }\n    },\n  });\n\n=head2 add_schema\n\n  $js-\u003eadd_schema($uri =\u003e $schema);\n  $js-\u003eadd_schema($schema);\n\nIntroduces the (unblessed, nested) Perl data structure\nrepresenting a JSON Schema to the implementation, registering it under the indicated URI if\nprovided, and all identifiers found within the document will be resolved against this URI (if\nprovided) and added as well. C\u003c''\u003e will be used if no other identifier can be found within.\n\nYou B\u003cMUST\u003e call C\u003cadd_schema\u003e or L\u003c/add_document\u003e (below) for any external resources that a schema may reference via C\u003c$ref\u003e\nbefore calling L\u003c/evaluate\u003e, other than the standard metaschemas which are loaded from a local cache\nas needed.\n\nIf you add multiple schemas (either with this method, or implicitly via L\u003c/evaluate\u003e) with no root\nidentifier (either provided explicitly in the method call, or via an C\u003c$id\u003e keyword at the schema\nroot), all such previous schemas are removed from memory and can no longer be referenced.\n\nIf there were errors in the document, will die with these errors;\notherwise returns the L\u003cJSON::Schema::Modern::Document\u003e that contains the added schema.\n\n=head2 add_document\n\n  $js-\u003eadd_document($uri =\u003e $document);\n  $js-\u003eadd_document($document);\n\nMakes the L\u003cJSON::Schema::Modern::Document\u003e (or subclass)\nobject, representing a JSON Schema, available to the evaluator. All identifiers known to the\ndocument are added to the evaluator's resource index; if the C\u003c$uri\u003e argument is provided, those\nidentifiers are resolved against C\u003c$uri\u003e as they are added.\n\nC\u003c$uri\u003e itself is also added to the resource index, referencing the root of the document itself.\n\nIf you add multiple documents (either with this method, or implicitly via C\u003c/add_schema\u003e or L\u003c/evaluate\u003e) with no root\nidentifier (either provided explicitly in the method call, or via an C\u003c$id\u003e keyword at the schema\nroot), all such previous schemas are removed from memory and can no longer be referenced.\n\nIf there were errors in the document, this method will die with these errors;\notherwise it returns the L\u003cJSON::Schema::Modern::Document\u003e object.\n\n=head2 add_format_validation\n\n  $js-\u003eadd_format_validation(all_lc =\u003e sub ($value) { lc($value) eq $value });\n\n=for comment we are the nine Eleven Deniers\n\nor\n\n  $js-\u003eadd_format_validation(no_nines =\u003e { type =\u003e 'number', sub =\u003e sub ($value) { $value =~ m/^[0-8]+$/ });\n\n  $js-\u003eadd_format_validation(8bits =\u003e { type =\u003e 'string', sub =\u003e sub ($value) { $value =~ m/^[\\x00-\\xFF]+$/ });\n\nAdds support for a custom format. If not supplied, the data type(s) that this format applies to\ndefaults to string; all values of any other type will automatically be deemed to be valid, and will\nnot be passed to the subref.\n\nAdditionally, you can redefine the definition for any core format (see L\u003c/Format Validation\u003e), but\nthe data type(s) supported by that format may not be changed.\n\nBe careful to not mutate the type of the value while checking it -- for example, if it is a string,\ndo not apply arithmetic operators to it -- or subsequent type checks on this value may fail.\n\nSee L\u003chttps://spec.openapis.org/registry/format/\u003e for a registry of known and useful formats; for\ncompatibility reasons, avoid defining a format listed here with different semantics.\n\n=head2 add_vocabulary\n\n  $js-\u003eadd_vocabulary('My::Custom::Vocabulary::Class');\n\nMakes a custom vocabulary class available to metaschemas that make use of this vocabulary.\nas described in the specification at\nL\u003c\"Meta-Schemas and Vocabularies\"|https://json-schema.org/draft/2020-12/json-schema-core.html#rfc.section.8.1\u003e.\n\nThe class must compose the L\u003cJSON::Schema::Modern::Vocabulary\u003e role and implement the\nL\u003cvocabulary|JSON::Schema::Modern::Vocabulary/vocabulary\u003e and\nL\u003ckeywords|JSON::Schema::Modern::Vocabulary/keywords\u003e methods, as well as\nC\u003c\u003c _traverse_keyword_\u003ckeyword name\u003e \u003e\u003e methods for each keyword. C\u003c\u003c _eval_keyword_\u003ckeyword name\u003e \u003e\u003e\nmethods are optional; when not provided, evaluation will always return a true result.\n\n=head2 add_media_type\n\n  $js-\u003eadd_media_type('application/furble' =\u003e sub ($content_ref) {\n    return ...;  # data representing the deserialized text for Content-Type: application/furble\n  });\n\nTakes a media-type name and a subref which takes a single scalar reference, which is expected to be\na reference to a string, which might contain wide characters (i.e. not octets), especially when used\nin conjunction with L\u003c/get_encoding\u003e below. Must return B\u003ca reference to a value of any type\u003e (which is\nthen dereferenced for the C\u003ccontentSchema\u003e keyword).\n\nThese media types are already known:\n\n=over 4\n\n=item *\n\nC\u003capplication/json\u003e - see L\u003cRFC 4627|https://datatracker.ietf.org/doc/html/rfc4627\u003e\n\n=item *\n\nC\u003capplication/schema+json\u003e - see L\u003cproposed definition|https://json-schema.org/draft/2020-12/json-schema-core.html#name-application-schemajson\u003e\n\n=item *\n\nC\u003capplication/schema-instance+json\u003e - see L\u003cproposed definition|https://json-schema.org/draft/2020-12/json-schema-core.html#name-application-schema-instance\u003e\n\n=item *\n\nC\u003capplication/octet-stream\u003e - passes strings through unchanged\n\n=item *\n\nC\u003capplication/x-www-form-urlencoded\u003e\n\n=item *\n\nC\u003capplication/x-ndjson\u003e - see L\u003chttps://github.com/ndjson/ndjson-spec\u003e\n\n=item *\n\nC\u003ctext/*\u003e - passes strings through unchanged\n\n=back\n\n=head2 get_media_type\n\nFetches a decoder sub for the indicated media type. Lookups are performed B\u003cwithout case sensitivity\u003e.\n\n=for stopwords thusly\n\nYou can use it thusly:\n\n  $js-\u003eadd_media_type('application/furble' =\u003e sub { ... }); # as above\n  my $decoder = $self-\u003eget_media_type('application/furble') or die 'cannot find media type decoder';\n  my $content_ref = $decoder-\u003e(\\$content_string);\n\n=head2 add_encoding\n\n  $js-\u003eadd_encoding('bloop' =\u003e sub ($content_ref) {\n    return \\ ...;  # data representing the deserialized content for Content-Transfer-Encoding: bloop\n  });\n\nTakes an encoding name and a subref which takes a single scalar reference, which is expected to be\na reference to a string, which SHOULD be a 7-bit or 8-bit string. Result values MUST be a scalar-reference\nto a string (which is then dereferenced for the C\u003ccontentMediaType\u003e keyword).\n\n=for stopwords natively\n\nEncodings handled natively are:\n\n=over 4\n\n=item *\n\nC\u003cidentity\u003e - passes strings through unchanged\n\n=item *\n\nC\u003cbase64\u003e - see L\u003cRFC 4648 §4|https://datatracker.ietf.org/doc/html/rfc4648#section-4\u003e\n\n=item *\n\nC\u003cbase64url\u003e - see L\u003cRFC 4648 §5|https://datatracker.ietf.org/doc/html/rfc4648#section-5\u003e\n\n=back\n\nSee also L\u003cHTTP::Message/encode\u003e.\n\n=head2 get_encoding\n\nFetches a decoder sub for the indicated encoding. Incoming values MUST be a reference to an octet\nstring. Result values will be a scalar-reference to a string, which might be passed to a media_type\ndecoder (see above).\n\nYou can use it thusly:\n\n  my $decoder = $self-\u003eget_encoding('base64') or die 'cannot find encoding decoder';\n  my $content_ref = $decoder-\u003e(\\$content_string);\n\n=head2 get\n\n  my $schema = $js-\u003eget($uri);\n  my ($schema, $canonical_uri) = $js-\u003eget($uri);\n\nFetches the Perl data structure represented by the indicated identifier (uri or\nuri-reference). When called in list context, the canonical URI of that location is also returned, as\na L\u003cMojo::URL\u003e. Returns C\u003cundef\u003e if the schema with that URI has not been loaded (or cached).\n\nNote that the data so returned may not be a JSON Schema, if the document encapsulating this location\nis a subclass of L\u003cJSON::Schema::Modern::Document\u003e (for example\nL\u003cJSON::Schema::Modern::Document::OpenAPI\u003e, which contains addressable locations of various semantic\ntypes).\n\n=head2 get_document\n\n  my $document = $js-\u003eget_document($uri_reference);\n\nFetches the L\u003cJSON::Schema::Modern::Document\u003e object (or subclass) that contains the provided\nidentifier (uri or uri-reference). C\u003cundef\u003e if the schema with that URI has not been loaded (or\ncached).\n\n=head1 CACHING\n\n=for stopwords preforking\n\nVery large documents, particularly those used by L\u003cOpenAPI::Modern\u003e, may take a noticeable time to be\nloaded and parsed. You can reduce the impact to your preforking application by loading all necessary\ndocuments at startup, and impact can be further reduced by saving objects to cache and then\nreloading them (perhaps by using a timestamp or checksum to determine if a fresh reload is needed).\n\nCustom L\u003cformat validations|/add_format_validation\u003e, L\u003cmedia types|/add_media_type\u003e or\nL\u003cencodings|/add_encoding\u003e are not serialized, as they are represented by subroutine references, and\nwill need to be manually added after thawing.\n\n  sub get_evaluator (...) {\n    my $serialized_file = Path::Tiny::path($filename);\n    my $schema_file = Path::Tiny::path($schema_filename);\n    my $js;\n    if ($serialized_file-\u003estat-\u003emtime \u003c $schema_file-\u003estat-\u003emtime)) {\n      $js = JSON::Schema::Modern-\u003enew;\n      $js-\u003eadd_schema(decode_json($schema_file-\u003eslurp_raw));  # your application schema\n      my $frozen = Sereal::Encoder-\u003enew({ freeze_callbacks =\u003e 1 })-\u003eencode($js);\n      $serialized_file-\u003espew_raw($frozen);\n    }\n    else {\n      my $frozen = $serialized_file-\u003eslurp_raw;\n      $js = Sereal::Decoder-\u003enew-\u003edecode($frozen);\n    }\n\n    # add custom format validations, media types and encodings here\n    $js-\u003eadd_media_type(...);\n\n    return $js;\n  }\n\nSee also L\u003cOpenAPI::Modern/CACHING\u003e.\n\n=head1 LIMITATIONS\n\n=head2 Types\n\nPerl is a more loosely-typed language than JSON. This module delves into a value's internal\nrepresentation in an attempt to derive the true \"intended\" type of the value.\nThis should not be an issue if data validation is occurring\nimmediately after decoding a JSON payload, or if the JSON string itself is passed to this module.\nIf you are having difficulties, make sure you are using Perl's fastest and most trusted and\nreliable JSON decoder, L\u003cCpanel::JSON::XS\u003e.\nOther JSON decoders are known to produce data with incorrect data types,\nand data from other sources may also be problematic.\n\nFor more information, see L\u003cCpanel::JSON::XS/MAPPING\u003e.\n\n=head2 Format Validation\n\nBy default (and unless you specify a custom metaschema with the C\u003c$schema\u003e keyword or\nL\u003cJSON::Schema::Modern::Document/metaschema\u003e),\nformats are treated only as annotations, not assertions. When L\u003c/validate_formats\u003e is\ntrue, strings are also checked against the format as specified in the schema. At present the\nfollowing formats are supported (use of any other formats than these will always evaluate as true,\nbut remember you can always supply custom format handlers; see L\u003c/format_validations\u003e above):\n\n=over 4\n\n=item *\n\nC\u003cdate-time\u003e\n\n=item *\n\nC\u003cdate\u003e\n\n=item *\n\nC\u003ctime\u003e\n\n=item *\n\nC\u003cduration\u003e\n\n=item *\n\nC\u003cemail\u003e\n\n=item *\n\nC\u003cidn-email\u003e\n\n=item *\n\nC\u003chostname\u003e\n\n=item *\n\nC\u003cidn-hostname\u003e\n\n=item *\n\nC\u003cipv4\u003e\n\n=item *\n\nC\u003cipv6\u003e\n\n=item *\n\nC\u003curi\u003e\n\n=item *\n\nC\u003curi-reference\u003e\n\n=item *\n\nC\u003ciri\u003e\n\n=item *\n\nC\u003cuuid\u003e\n\n=item *\n\nC\u003cjson-pointer\u003e\n\n=item *\n\nC\u003crelative-json-pointer\u003e\n\n=item *\n\nC\u003cregex\u003e\n\n=back\n\nA few optional prerequisites are needed for some of these (if the prerequisite is missing,\nvalidation will always succeed, unless draft2020-12 is in use with the Format-Assertion vocabulary\ndeclared in the metaschema, in which case use of the format will produce an error).\n\n=over 4\n\n=item *\n\nC\u003cdate-time\u003e and C\u003cdate\u003e require L\u003cTime::Moment\u003e\n\n=item *\n\nC\u003cdate-time\u003e also requires \u003cDateTime::Format::RFC3339\u003e\n\n=item *\n\nC\u003cemail\u003e and C\u003cidn-email\u003e require L\u003cEmail::Address::XS\u003e version 1.04 (or higher)\n\n=item *\n\nC\u003chostname\u003e and C\u003cidn-hostname\u003e require L\u003cData::Validate::Domain\u003e version 0.13 (or higher)\n\n=item *\n\nC\u003cidn-hostname\u003e also requires L\u003cNet::IDN::Encode\u003e\n\n=back\n\n=head2 Specification Compliance\n\nThis implementation is now fully specification-compliant (for versions\ndraft4, draft6, draft7, draft2019-09, draft2020-12),\nbut until version 1.000 is released, it is\nstill deemed to be missing some optional but quite useful features, such as:\n\n=for stopwords Mojolicious\n\n=over 4\n\n=item *\n\nloading schema documents from disk\n\n=item *\n\nloading schema documents from the network\n\n=item *\n\nloading schema documents from a local web application (e.g. L\u003cMojolicious\u003e)\n\n=item *\n\nadditional output formats beyond C\u003cflag\u003e, C\u003cbasic\u003e, and C\u003cterse\u003e (L\u003chttps://json-schema.org/draft/2020-12/json-schema-core.html#rfc.section.12\u003e)\n\n=back\n\n=head1 SECURITY CONSIDERATIONS\n\nThe C\u003cpattern\u003e and C\u003cpatternProperties\u003e keywords evaluate regular expressions from the schema,\nthe C\u003cregex\u003e format validator evaluates regular expressions from the data, and some keywords\nin the Validation vocabulary perform floating point operations on potentially-very large numbers.\nNo effort is taken (at this time) to sanitize the regular expressions for embedded code or\ndetect potentially pathological constructs that may pose a security risk, either via denial of\nservice or by allowing exposure to the internals of your application. B\u003cDO NOT USE SCHEMAS FROM\nUNTRUSTED SOURCES.\u003e\n\n(In particular, see vulnerability\nL\u003cperl5363delta/CVE-2023-47038-Write-past-buffer-end-via-illegal-user-defined-Unicode-property\u003e,\nwhich was fixed in Perl releases 5.34.3, 5.36.3 and 5.38.1.)\n\n=head1 SEE ALSO\n\n=for stopwords OpenAPI\n\n=over 4\n\n=item *\n\nL\u003cjson-schema-eval\u003e\n\n=item *\n\nL\u003chttps://json-schema.org\u003e\n\n=item *\n\nL\u003cRFC8259: The JavaScript Object Notation (JSON) Data Interchange Format|https://datatracker.ietf.org/doc/html/rfc8259\u003e\n\n=item *\n\nL\u003cRFC3986: Uniform Resource Identifier (URI): Generic Syntax|https://datatracker.ietf.org/doc/html/rfc3986\u003e\n\n=item *\n\nL\u003cTest::JSON::Schema::Acceptance\u003e: contains the official JSON Schema test suite\n\n=item *\n\nL\u003cJSON::Schema::Tiny\u003e: a more stripped-down implementation of the specification, with fewer dependencies and faster evaluation\n\n=item *\n\nL\u003chttps://json-schema.org/draft/2020-12/release-notes.html\u003e\n\n=item *\n\nL\u003chttps://json-schema.org/draft/2019-09/release-notes.html\u003e\n\n=item *\n\nL\u003chttps://json-schema.org/draft-07/json-schema-release-notes.html\u003e\n\n=item *\n\nL\u003chttps://json-schema.org/draft-06#draft-06-release-notes\u003e\n\n=item *\n\nL\u003chttps://json-schema.org/draft-04/draft-zyp-json-schema-04\u003e\n\n=item *\n\nL\u003cUnderstanding JSON Schema|https://json-schema.org/understanding-json-schema\u003e: tutorial-focused documentation\n\n=item *\n\nL\u003cOpenAPI::Modern\u003e: a parser and evaluator for OpenAPI v3.1 documents\n\n=item *\n\nL\u003cMojolicious::Plugin::OpenAPI::Modern\u003e: a Mojolicious plugin providing OpenAPI functionality\n\n=item *\n\nL\u003cTest::Mojo::Role::OpenAPI::Modern\u003e: test your Mojolicious application's OpenAPI compliance\n\n=back\n\n=head1 AVAILABILITY\n\nThis distribution and executable is available on modern Debian versions (via C\u003capt-get\u003e) as the\nC\u003clibjson-schema-modern-perl\u003e package.\n\n=head1 SUPPORT\n\nBugs may be submitted through L\u003chttps://github.com/karenetheridge/JSON-Schema-Modern/issues\u003e.\n\nI am also usually active on irc, as 'ether' at C\u003circ.perl.org\u003e and C\u003circ.libera.chat\u003e.\n\n=for stopwords OpenAPI\n\nYou can also find me on the L\u003cJSON Schema Slack server|https://json-schema.slack.com\u003e and L\u003cOpenAPI Slack\nserver|https://open-api.slack.com\u003e, which are also great resources for finding help.\n\n=head1 AUTHOR\n\nKaren Etheridge \u003cether@cpan.org\u003e\n\n=head1 COPYRIGHT AND LICENCE\n\nThis software is copyright (c) 2020 by Karen Etheridge.\n\nThis is free software; you can redistribute it and/or modify it under\nthe same terms as the Perl 5 programming language system itself.\n\nSome schema files have their own licence, in share/LICENSE.\n\n=cut\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarenetheridge%2FJSON-Schema-Modern","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarenetheridge%2FJSON-Schema-Modern","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarenetheridge%2FJSON-Schema-Modern/lists"}