# Data : JSON Schema \[ [specs](https://json-schema.org/specification) | [guide](https://json-schema.org/understanding-json-schema) ] JSON-based format to define the structure of JSON data. #### Basics > "JSON Schema does not have the full verification capabilities of a relational database. ... For example, you cannot ensure that the values in a particular field also appear as the primary key in another file (foreign key constraint). In general, JSON Schema can look at one object (or file of similar objects) but not across multiple datasets." > — [Chuck Connell](https://towardsdatascience.com/json-schema-integrity-checking-for-nosql-data-b1255f5ea17d) Media types: `application/schema+json`, `application/schema-instance+json` ###### Dialects JSON Schema "dialects" are compatible with the core but may: - add keywords - remove keywords - modify behavior of keywords The default dialect is the [2020-12 draft](https://json-schema.org/draft/2020-12/schema). ###### Schemas and Subschemas Schemas validate a value and are expressed as a JSON object or boolean. > [!info] > `{}` -> empty schema, matches all values | `true` → matches all values | `false` → matches none Schemas are recursive structures. A schema appearing within a schema document is a **subschema**. In this document, **schemas** will refer to both, and **root schemas** will refer to whole documents. Root schemas *may* (and *should*) specify the dialect they conform to. Otherwise, validators will assume some default. ```JSON "$schema": "https://json-schema.org/draft/2020-12/schema" ``` ###### IDs All schemas *may* (and root schemas *should*) contain a URI id which can then be referenced both within the same document and in external documents. ```JSON "$id": "https://yourdomain.com/schemas/myschema.json" ``` #### Keywords ###### Universal ```JSON type : <type> -or- [ type1, ... ] # array, boolean, integer, null, number, object, string # Annotations (not strictly used for validation) title : <str> description : <str> default : <*> # used for docs, not to fill in missing values examples : [ ... ] # values that validate against schema readOnly : true writeOnly : true deprecated : true # Misc $comment : <str> enum : [ ... ] # contains 1+ unique values const : <*> # restrict to single value # Defs & Refs $defs : { # place to define named subschemas <name> : <schema> } $ref : <uri> # external root schema $ref : #<json-pointer> # local subschema (JSON Pointer example: /foo/0/bar) $ref : <uri>#<json-pointer> # external subschema (not recommended) # Composition allOf : [ <schema1>, ... ] # must be valid against all of the subschemas anyOf : [ <schema1>, ... ] # must be valid against any of the subschemas oneOf : [ <schema1>, ... ] # must be valid against exactly one of the subschemas not : <schema> # must not be valid against the given schema ``` ###### Numbers ```JSON multipleOf : <posnum> minimum : <num> maximum : <num> exclusiveMinimum : <num> exclusiveMaximum : <num> ``` ###### Strings ```JSON format : <format> # validators may treat this as either annotation or assertion # see list of built-in formats below minLength : <posint> maxLength : <posint> pattern : "^...$ # JS regex syntax ``` ###### Arrays ```JSON # List Validation: sequence of arbitrary length, each item matches the same schema items : <schema> # applied to every item in array # Tuple Validation: sequence of fixed length, each item may have a different schema items : false # disallow items other than those in prefixItems prefixItems : [ <schema1>, ... ] # applied positionally contains : <schema> # must validate against at least one item minContains : <posint> # affect quantity needed for "contains" maxContains : <posint> minItems : <posint> maxItems : <posint> uniqueItems : true ``` ###### Objects ```JSON # By default: # - properties listed here are not required to be present # - properties not listed here are skipped during validation properties : { <prop_name> : <schema> } patternProperties : { "^...quot; : <schema> } # applied to properties that aren't handled above # only aware of locally-declared properties, not external definitions additionalProperties : <schema> additionalProperties : false # disallow additional properties # new alternative to additionalProperties - aware of properties in external definitions unevaluatedProperties : <schema> unevaluatedProperties : false required : [ <prop_name1>, ... ] # validate property names against schema, irrespective of their values propertyNames : <schema> minProperties : <posint> maxProperties : <posint> ``` #### Formats ###### Built-in ```JSON regex : see ECMA 262 # Dates & Times (RFC 3339 / ISO8601) date-time : ex: 2018-11-13T20:20:39+00:00 time : ex: 20:20:39+00:00 date : ex: 2018-11-13 duration : see ISO 8601 ABNF for “duration”; ex: "P3D" -> 3 days # Email Addresses email : see RFC 5321, section 4.1.2 idn-email : internationalized form; see RFC 6531 # Hostnames hostname : internet host name; see RFC 1123 section 2.1 idn-hostname : internationalized form; see RFC 5890 section 2.3.2.3 # IP Addresses ipv4 : see dotted-quad ABNF syntax in RFC 2673 section 3.2 ipv6 : see RFC 2373 section 2.2 # Resource Identifiers uuid : see RFC 4122; ex: 3e4666bf-d5e5-4aa7-b8ce-cefe41c7568a uri : for absolute paths; see RFC 3986 uri-reference : for relative paths; see RFC 3986 section 4.1 iri : internationalized uri; see RFC 3987 iri-reference : internationalized uri-reference; see RFC 3987 # JSON Pointer json-pointer : see RFC 6901; ex: "/foo/bar" ("#/foo/bar" should use uri-reference) relative-json-pointer : relative JSON pointer ``` ## Python #### fastjsonschema \[ [pypi](https://pypi.org/project/fastjsonschema/) | [src](https://github.com/horejsek/python-fastjsonschema/) | [docs](https://horejsek.github.io/python-fastjsonschema/) ] ```python from fastjsonschema import compile, compile_to_code, validate from fastjsonschema import JsonSchemaException, JsonSchemaDefinitionException JsonSchemaException # raised by validation function # properties: message, name, path, rule JsonSchemaDefinitionException # raised by compile() validate( definition, data ) # for convenience; slower than compiling first compile( definition ) # returns validation function that accepts data my_validator = compile( dict( type="string" ) ) my_validator( "hello" ) ```