Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON Schema regarding use of $ref

I understand that $ref takes a URI to a json schema to use but where does $ref : "#" point to? Does it just mean use the current schema for this block level? Or does it mean to use the root level schema defined in the root level id? Thanks

EDIT: So if I have:

"items": {         "anyOf": [             { "$ref": "#" },             { "$ref": "#/definitions/schemaArray" }         ],         "default": {}     } 

Because it lacks an id field it will attempt to validate the instance items with the root schema first and then if that fails try to validate it with the schemaArray schema defined in the definitions schema, right?

So if I change it to:

 "items": {             "id" : "#/items",             "anyOf": [                 { "$ref": "#" },                 { "$ref": "#/definitions/schemaArray" }             ],             "default": {}         } 

Then the first subschema in anyOf array will point to the items schema itself?

EDIT #2: Okay so if I had:

 "items": {         "id" : "itemSchema",         "anyOf": [             { "$ref": "#" },             { "$ref": "#/definitions/schemaArray" }         ],         "default": {}     } 

and

"stringArray": {         "type": "array",         "items": { "$ref" : "itemSchema" },         "minItems": 1,         "uniqueItems": true     } 

"stringArray"'s "items" field would be validated against the above "itemsSchema"?

Also does the second $ref in 'anyOf' work by going to the root and then traversing down the path till it hits that schema? Thanks!

like image 968
hunterc Avatar asked Jul 11 '13 13:07

hunterc


People also ask

What is $ref in JSON Schema?

In a JSON schema, a $ref keyword is a JSON Pointer to a schema, or a type or property in a schema. A JSON pointer takes the form of A # B in which: A is the relative path from the current schema to a target schema. If A is empty, the reference is to a type or property in the same schema, an in-schema reference.

What is JSON Schema?

JSON Schema is a JSON media type for defining the structure of JSON data. JSON Schema provides a contract for what JSON data is required for a given application and how to interact with it. JSON Schema is intended to define validation, documentation, hyperlink navigation, and interaction control of JSON data.

What is JSON Schema additionalProperties?

The additionalProperties keyword is used to control the handling of extra stuff, that is, properties whose names are not listed in the properties keyword or match any of the regular expressions in the patternProperties keyword. By default any additional properties are allowed.

What is required in JSON Schema?

What is JSON Schema? JSON Schema is a JSON-based format for defining the structure of JSON data. It provides a contract for what JSON data is required for a given application and how to interact with it. It can be used for validation, documentation, hyperlink navigation, and interaction control of JSON data.


1 Answers

OK: each $ref is resolved into a full URI. Once that is done, all your questions are answered by asking the question: What schema would I end up with, if I simply fetched that URI? Where the $ref is, how it was loaded, all of that is irrelevant - it's entirely dependent on the resolved URI.

The library might take some shortcuts (like caching documents so they are only fetched once, or trusting one schema to "speak for" another), but those are all implementation details.

Response to original question:

# is not special: all values of $ref are resolved as URIs relative to the current document (or the closest value of "id", if there is one).

Therefore, if you haven't used "id", then # will point to the root of the schema document. If you fetched your schema from http://example.com/schema, then a {"$ref": "#"} anywhere inside that will resolve to http://example.com/schema#, which is the document itself.

It is different when you use "id", because it changes the "base" schema against which the $ref is resolved:

{     "type": "array",     "items": {         "id": "http://example.com/item-schema",         "type": "object",         "additionalProperties": {"$ref": "#"}     } } 

In that example, the $ref resolves to http://example.com/item-schema#. Now, if your JSON Schema setup trusts the schema it already has, then it can re-use the value from "items".

However, the point is there is nothing special about # - it just resolves to a URI like any other.

Response to EDIT 1:

Your first example is correct.

However, your second is unfortunately not. This is because of the way that fragments resolution works for URIs: one fragment completely replaces another. When you resolve the # against the "id" value of #/items, you don't end up with #/items again - you end up with #. So in your second example, the first entry in "anyOf" will still resolve to the root of the document, just as in the first example.

Response to EDIT 2:

Assuming the document is loaded from http://example.com/my-schema, the full URIs of your two $refs are:

  • http://example.com/itemSchema#
  • http://example.com/itemSchema#/definitions/schemaArray

For the first one, the library may use the schema it already has, but it might not - after all, looking at the URIs, http://example.com/my-schema might not be trusted to accurately represent http://example.com/itemSchema.

For the second one - that's not going to work, because the "itemSchema" doesn't have a "definitions" section, so that $ref won't resolve properly at all.

like image 192
cloudfeet Avatar answered Sep 28 '22 05:09

cloudfeet