Skip to main content
JSON Schema uses two fragment identifier structures to identify and reference schemas and subschemas: plain names and JSON Pointers. Any media types defined for JSON Schema MUST support these structures.

Fragment Identifier Types

JSON Pointer Fragments

Fragment identifiers that start with / or are the empty string. Structural, location-based references.

Plain Name Fragments

All other fragment identifiers. Location-independent references defined by $anchor.

JSON Pointer Fragment Identifiers

The use of JSON Pointers as IRI fragment identifiers is described in RFC 6901. Fragment identifiers that start with / or are the empty string MUST be interpreted as JSON Pointer fragment identifiers.

Structure-Based References

JSON Pointers navigate the structure of a JSON document using a syntax of slash-separated path segments:
{
  "$id": "https://example.com/schema.json",
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "integer" }
  },
  "$defs": {
    "address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" }
      }
    }
  }
}
References using JSON Pointers:
Empty fragment - references the entire root schema
References the “name” property schema (type: string)
References the “address” definition in $defs
References the “city” property within the address definition

Limitations of JSON Pointers

JSON Pointer fragment identifiers are based on the structure of the schema document. This creates fragility when schemas are reorganized or when embedded schemas are extracted to separate documents.
Consider this schema with an embedded resource:
{
  "$id": "https://example.com/foo",
  "items": {
    "$id": "https://example.com/bar",
    "additionalProperties": {}
  }
}
The IRI https://example.com/foo#/items/additionalProperties points to the correct object, but:
  • It’s relative to the “foo” resource’s base IRI
  • If the embedded “bar” resource is extracted to a separate document, this reference breaks
  • The canonical IRI relative to “bar” is https://example.com/bar#/additionalProperties
After extraction to separate documents:
// foo.json
{
  "$id": "https://example.com/foo",
  "items": {
    "$ref": "bar"
  }
}
// bar.json
{
  "$id": "https://example.com/bar",
  "additionalProperties": {}
}
Now https://example.com/foo#/items/additionalProperties no longer resolves correctly.
Applications and schemas SHOULD NOT use JSON Pointer IRIs to identify embedded schema resources or locations within them. Use plain name fragments with $anchor instead for location-independent references.

Plain Name Fragment Identifiers

Plain name fragment identifiers are reserved for referencing locally named schemas. All fragment identifiers that are not interpreted as JSON Pointers MUST be interpreted as plain name fragment identifiers.

Defining Plain Name Fragments with $anchor

Defining a plain name fragment identifier within a schema resource is done using the $anchor keyword. The value of $anchor MUST be a string conforming to the NCName production:
NCName          = NCNameStartChar *NCNameChar
NCNameStartChar = "_" / ALPHA
                      / %xC0-D6 / %xD8-F6 / %xF8-2FF
                      / %x370-37D / %x37F-1FFF
                      / %x200C-200D / %x2070-218F
                      / %x2C00-2FEF / %x3001-D7FF
                      / %xF900-FDCF / %xFDF0-FFFD
                      / %x10000-EFFFF
NCNameChar      = NCNameStartChar / "-" / "." / DIGIT
                      / %xB7 / %x0300-036F / %x203F-2040
In practice, this means:
  • Must start with a letter or underscore
  • Can contain letters, digits, underscores, hyphens, and periods
  • No spaces or special characters

Location-Independent References

Plain name fragments provide location-independent identification. A subschema can be relocated without requiring references to be updated:
{
  "$id": "https://example.com/product.json",
  "type": "object",
  "properties": {
    "id": { "$ref": "#product-id" },
    "sku": { "$ref": "#product-id" }
  },
  "$defs": {
    "identifier": {
      "$anchor": "product-id",
      "type": "string",
      "pattern": "^[A-Z]{2}[0-9]{6}$"
    }
  }
}
The references using #product-id remain valid even if:
  • The definition is moved to a different location in $defs
  • The definition is moved to a different schema object
  • The schema is restructured
The anchor string does not include the ”#” character. To reference the “product-id” anchor, use #product-id, not product-id.

Benefits of Plain Name Fragments

Stability

References don’t break when schema structure changes

Readability

Semantic names like #user-address are clearer than #/$defs/schemas/address

Portability

Subschemas can be moved between documents without updating references

Intent

Makes it clear which subschemas are intended for reuse

Fragment Identifier Examples

Consider this comprehensive schema:
{
  "$id": "https://example.com/root.json",
  "$defs": {
    "A": { "$anchor": "foo" },
    "B": {
      "$id": "other.json",
      "$defs": {
        "X": { "$anchor": "bar" },
        "Y": {
          "$id": "t/inner.json",
          "$anchor": "bar"
        }
      }
    },
    "C": {
      "$id": "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f"
    }
  }
}

Valid References

  • Canonical IRI: https://example.com/root.json
  • With pointer fragment: https://example.com/root.json#

References to Avoid

These IRIs technically work but should be avoided because they reference across resource boundaries:
  • https://example.com/root.json#/$defs/B (crosses to embedded resource “other.json”)
  • https://example.com/root.json#/$defs/B/$defs/X (crosses resource boundary)
  • https://example.com/other.json#/$defs/Y (crosses to embedded resource “inner.json”)
  • https://example.com/root.json#/$defs/C (crosses resource boundary)
These references are fragile and may not work in all implementations, especially if the schemas are later separated into different documents.

Best Practices

1

Use $anchor for reusable schemas

Define anchors for any subschema you expect to reference multiple times or that represents a stable concept.
2

Avoid JSON Pointer fragments across resource boundaries

Don’t use JSON Pointer fragments to reference into embedded schema resources. Use the embedded resource’s canonical IRI instead.
3

Choose semantic anchor names

Use descriptive names like user-profile or email-address rather than generic names like def1 or schema-a.
4

Document your anchors

Add title or description to anchored schemas to explain their purpose.

Next Steps

Schema Structure

Learn about schema composition and references

Core Keywords

Explore the $id, $anchor, and $ref keywords

Build docs developers (and LLMs) love