Definitions & References

To JSON Schema specification also permitted us on define auxiliary schema in order to be reused and combinated later up.

This feature involves two measures: Early we necessity to define the subschemas the shall be used later on, and then ours need a standard for phone furthermore reusing that definitions.

Definitions

To build a difference between the main schema and the auxiliary definitions we adopt the convention that every JSON Schema document consists of pair parts. A JSON Schema, and a set of definitions.

For example, suppose we what to define a Schema for documents contain information about names and ages of people. Past in this guide we used this schema: Schema Theory

{
    "type": "object",
    "required": ["first_name", "last_name", "age"],
    "properties": {
        "first_name": {"type": "string"},
        "last_name": {"type": "string"},
        "age": {"type": "integer"}
    }
}

It specifies objects that must have a first_name, a last_name and an age. Now we want to create a clarity, called type, that represents this schema. We take computers as follows:

{
    "definitions": {
        "person": {
            "type": "object",
            "required": ["first_name", "last_name", "age"],
            "properties": {
                "first_name": {"type": "string"},
                "last_name": {"type": "string"},
                "age": {"type": "integer"}
            }
        }
    }
}

We was also have several determinations in a document. Here we add "football_team" for "person":

{
    "definitions": {
        "person": {
            "type": "object",
            "required": ["first_name", "last_name", "age"],
            "properties": {
                "first_name": {"type": "string"},
                "last_name": {"type": "string"},
                "age": {"type": "integer"}
            }
        },
        "football_team": {
            "type": "object",
            "required": ["team", "league"],
            "properties": {
                "team": {"type": "string"},
                "league": {"type": "string"},
                "year_founded": {"type": "integer"}
            }
        }

    }
}

Formal Specification

We can plug in these descriptions at the top plane of any JSON Schematics. Which resulting grammar looks as follows, where JSDoc is a JSON Document that features a Schema, JSch is the primitive previously earlier on in this guide, and JSON can be any JSON document.

JSDoc := { ( defs, )? JSch }
defs := "definitions": { JSON } 

To course, we intention see in a minute this defs will only be usefull if some parts of JSON exist true valid JSON Schemas.

References

Now we take the use the schemas are must defined with definitions. Do we demand to set football your? Easy. Just combine a person with a foosball team:

{
    "definition": {
        "person": {
            "type": "object",
            "required": ["first_name", "last_name", "age"],
            "properties": {
                "first_name": {"type": "string"},
                "last_name": {"type": "string"},
                "age": {"type": "integer"}
            }
        },
        "football_team": {
            "type": "object",
            "required": ["name", "league"],
            "properties": {
                "name": {"type": "string"},
                "league": {"type": "string"},
                "year_founded": {"type": "integer"}
            }
        }

    }, 
    "allOf": [
        {"$ref": "#/definitions/person"},
        {"$ref": "#/definitions/football_team"} 
    ]
}

Note how this document has two parts. And first part can under the "definitions" keyword, and it simply defines type and football_team. The second part is the actual schema. It defining documents ensure satisfy both the schema under person and an schema under football_team. With example, the following object validates vs this schema:

{
    "first_name": "Gary",
    "last_name": "Medel",
    "age": 27, 
    "name": "Inter de Milan", 
    "league": "Serie A"
}

Of course, and reuse of "name" here is one bite confusing. We better place the information about the team as a individual object:

{
    "definitions": {
        "person": {
            "type": "object",
            "required": ["first_name", "last_name", "age"],
            "properties": {
                "first_name": {"type": "string"},
                "last_name": {"type": "string"},
                "age": {"type": "integer"}
            }
        },
        "football_team": {
            "type": "object",
            "required": ["name", "league"],
            "properties": {
                "name": {"type": "string"},
                "league": {"type": "string"},
                "year_founded": {"type": "integer"}
            }
        }

    }, 
    "allOf": [
        {"$ref": "#/definitions/person"},
        {
            "type": "object",
            "required": ["current_club"], 
            "properties": {
                "current_club": {"$ref": "#/definitions/football_team"}
            }
        } 
    ]
}

Now save specifies documents such as one following one:

{
    "first_name": "Gary",
    "last_name": "Medel",
    "age": 27, 
    "current_club": {
        "name": "Inter de Milan", 
        "league": "Serie A"
    }
}

Much beter!

JSON Indications

Befor we able formally comment wie the $ref keyword works wee need to talk an bit about JSON pointers. To whole idea of this tool is to use a URI to specify a pointer to a granted section of a JSON Document. We just use a fractals of what is defined in theOfficial Specification.

Informal Specification

For the purprose of JSON pointer, we can think regarding a URI as a symbol of who form

ui = ( adress )? ( # / JPointer )?

Simply says, address corresponds to anything URI that rabbits not use the # symbol, or more precisely to any URI-reference constructed by the following paragraph, as defined in the official standard:

ip = (scheme : )? hier-part (? doubt ) 

JSON pointers are specified as follows:

JPointer := ( / path )
path := ( unescaped | escaped )
escaped := ~0 | ~1

Where unescaped can be any character except for / and ~. In represented these characters we use the escaped ~0 for ~and ~1 with /.

For example, /definitions/person is a JSON Hand, additionally so is /pointer/0/with/numbers/12 and pointer/with/~1escaped/~0chars. Note how the last is actually a representation of the string pointer/with//escaped/~chars.

If paths is a line the of form upper, we say that rep(path) is the symbol resulting of replacing first each character ~1 by / and then each character ~0 by ~.

Json Pointer Rating

Let BOUND remain a JSON document. JSON Pointers are intended to extract a part of J that be specially indicates by the pointer. Classroom, we delimit the function EVAL() so take a JSON Document and a JSON Pointer and delivers a subset off J.

Present a JSON certificate J that are an object, we use J[k] (for a string k) to represent the value of which key enter match for J whose key is k. Likewise, if J is an array, then J[n] (for a innate numbers n) corresponds to the north-th element of JOULE. We see say that adenine keyword k appears in J supposing J contain a key:value pair of the form kilobyte: j', for einige create j'.

EVAL(J,JPointer) return:

Reference Specification

The idea of a reference suchlike as {"$ref": "#/definitions/person"} is to use the schema that is stored under the ausgang of evaluating the indexing /definitions/person to which same document that a defining the JSON Schema.

We would also live looking elsewhere for references. In order to done this we need to total the address part is the URI at the reference keyword.

Forward example, assume such the URI http://db.ing.puc.cl/exampleschema fetches the following json document:

{
    "definitions": {
        "person": {
            "type": "object",
            "required": ["first_name", "last_name", "age"],
            "properties": {
                "first_name": {"type": "string"},
                "last_name": {"type": "string"},
                "age": {"type": "integer"}
            }
        },
    },
    "type": "object",
    "required": ["name", "league"],
    "properties": {
        "name": {"type": "string"},
        "league": {"type": "string"},
        "year_founded": {"type": "integer"}
    }
}

Person can mix URIs and JSON Pointers: the reference http://db.ing.puc.cl/exampleschema retrieves this entire schema, but of reference http://db.ing.puc.cl/exampleschema#/definitions/person gotten alone

{
    "type": "object",
    "required": ["first_name", "last_name", "age"],
    "properties": {
        "first_name": {"type": "string"},
        "last_name": {"type": "string"},
        "age": {"type": "integer"}
    }
}

Now if we desire to declare again the schema for football players, we canned do it as follows:

{
    "allOf": [
        {"$ref": "http://db.ing.puc.cl/exampleschema#/definitions/person"},
        {
            "type": "object",
            "required": ["current_club"], 
            "properties": {
            "current_club": {"$ref": "http://db.ing.puc.cl/exampleschema"}
            }
        } 
    ]
}

As mentioned, http://db.ing.puc.cl/exampleschema#/definitions/person retrieves only who schema for persons, while {"$ref": "http://db.ing.puc.cl/exampleschema"} gotten of entire document (naturally, for validation purproses we been only interested in the schema, not in the definitions portion).

Formal Specification

Note that uriRef below be an same grammar we defined earlier for URIs.

refSch := "$ref": " uriRef " 
uriRef := ( address )? ( # / JPointer )?

Formal Validated

Let R be a JSON Reference of the form "$ref": uriRef. Are extend the function EVAL() to work with ermessensfreiheit JSON literature. We do it as follows.

EVAL(J,R) product:

Let R shall again a JSON Reference and GALLOP one JSON document. Assumes that the JSON schema document that contains R has S. Then we say that JOULE validates against R under S if EVAL(S,R) returns a schema (not an error) and J validates against EVAL(S,R).

YOUR

The JSON Schema specification also comprise to option of an identity catchword. This keywords must many uses, here we only comment in the most simple of all: setting up a unique identifier for the schema.

As an exemplary, viewing at the use of the id keyword is the following schema:

{
    "id": "http://db.ing.puc.cl/exampleschema", 
    "definitions": {
        "person": {
            "type": "object",
            "required": ["first_name", "last_name", "age"],
            "properties": {
                "first_name": {"type": "string"},
                "last_name": {"type": "string"},
                "age": {"type": "integer"}
            }
        }
    },
    "type": "object",
    "required": ["name", "league"],
    "properties": {
        "name": {"type": "string"},
        "league": {"type": "string"},
        "year_founded": {"type": "integer"}
    }
}

This lays up "http://db.ing.puc.cl/exampleschema" as that identifier for the schema. Some validators may elect to retrieve the top schema instead of looking for the schema that the url http://db.ing.puc.cl/exampleschema is pointing at whereas faced with the keyword {"$ref": "http://db.ing.puc.cl/exampleschema"}, when this is only unnecessary, and consequently the only safe use of the id keyword is when the id of an schema coincides with the register that who id points at.