Skip to content

Clarify usage of $ref with properties not provided in definitions #1097

Closed
@cybtachyon

Description

@cybtachyon

From @ThatGuyCND @rjmill and myself:

Based on reading https://json-schema.org/understanding-json-schema/structuring.html#using-id-with-ref:
In an effort to reuse definitions and lessen code duplication, common schemas are abstracted into smaller “chunks.”
As noted by the documentation linked above, you would either:

  1. Use local definitions to define these and then reference them via fragment #/definitions
  2. Define them with $id (id in draft-04) and call them that way : #<$id>
  3. Need to use fragment #/properties

Assumptions:

  • Given the structure of the files below, because id is not defined, and the properties are specified in an external file, and JSON-Schema documentation notes that definitions are not required, one would need to use #/properties/… in order to interpolate the defined values.
  • When you use $id, you're explicitly setting the "canonical" URI for that schema resource. Unless $id specifies an absolute URI, the URI-reference is resolved against the current base URI to create an absolute URI.
    The thing to note here is the base URI. $ref (unless it's an absolute URI) is resolved against the current base URI to create a full URI.
    When the base URI isn't explicitly set in the root schema via $id, it defaults to the retrieval URI. So if you retrieved the first one from http://example.com/foo/image_embed.json, the "$ref": "link.json" would be resolved as "$ref": "http://example.com/foo/link.json" as per standard URI resolution rules.
    As long as your JSON Schema implementation fetches unknown URIs, and the two schemas are retrievable next to each other, then that should work.
    Worth noting, JSON Schema implementations aren't required to fetch unknown URIs. Many do, but it's not a requirement. The URI is being used as an identifier, not a location.
  • $id as a root-level value and $id as a property-level value in a schema act on different sides of the JSON Pointer. A root level $id acts on the left side of the #/ pointer, while a property-level $id acts on the right side.

Examples:

image_embed.json:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "title": "Image embed",
  "description": "A method for displaying images",
  "category": "component",
  "type": "object",
  "format": "grid",
  "properties": {
    "link": {
      "entity": "link",
      "type": "object",
      "format": "grid",
      "options": {
        "grid_columns": 6
      },
      "properties": {
        "href": {
          "$ref": "link.json#/properties/href",
          "options": {
            "grid_columns": 3
          }
        },
        "title": {
          "$ref": "link.json#/properties/title",
          "options": {
            "grid_columns": 3
          }
        }
      },
      "required": ["href"]
    }
  }
}

link.json:

{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "category": "atom",
  "title": "Link",
  "entity": "link",
  "type": "object",
  "format": "grid",
  "properties": {
    "href": {
      "title": "URL",
      "type": "string",
      "format": "url",
      "options": {
        "grid_columns": 4
      }
    },
    "title": {
      "title": "Title attribute",
      "description": "Shown on mouseover.",
      "type": "string",
      "options": {
        "grid_columns": 4
      }
    }
  }
}

the bits in question: "$ref": "link.json#/properties/href", and "$ref": "link.json#/properties/title".

Why is this important enough to merit changes to the docs?

Goal

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions