Composition

This section covers advanced schema composition features in dotjson that enable code reuse, complex patterns, and sophisticated data structures.

Schema References with $defs

References allow you to define a schema once and reuse it multiple times throughout your document. This promotes consistency and maintainability.

Basic Reference Pattern

Define reusable schemas in $defs and reference them with $ref:

{
  "type": "object",
  "properties": {
    "primaryContact": { "$ref": "#/$defs/person" },
    "secondaryContact": { "$ref": "#/$defs/person" }
  },
  "required": ["primaryContact"],
  "$defs": {
    "person": {
      "type": "object",
      "properties": {
        "firstName": { "type": "string" },
        "lastName": { "type": "string" },
        "email": { "type": "string", "format": "email" },
        "phone": { "type": "string" }
      },
      "required": ["firstName", "lastName", "email"]
    }
  }
}
{
  "primaryContact": {
    "firstName": "Alice",
    "lastName": "Johnson",
    "email": "[email protected]",
    "phone": "+1-555-0100"
  },
  "secondaryContact": {
    "firstName": "Bob",
    "lastName": "Smith",
    "email": "[email protected]",
    "phone": "+1-555-0101"
  }
}

Nested References

References can contain other references, creating modular schemas:

{
  "type": "object",
  "properties": {
    "company": { "$ref": "#/$defs/company" }
  },
  "required": ["company"],
  "$defs": {
    "address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "state": { "type": "string" },
        "postalCode": { "type": "string" },
        "country": { "type": "string" }
      },
      "required": ["street", "city", "country"]
    },
    "person": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "title": { "type": "string" },
        "email": { "type": "string", "format": "email" },
        "phone": { "type": "string" }
      },
      "required": ["name", "email"]
    },
    "company": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "headquarters": { "$ref": "#/$defs/address" },
        "ceo": { "$ref": "#/$defs/person" },
        "cto": { "$ref": "#/$defs/person" },
        "founded": { "type": "integer" }
      },
      "required": ["name", "headquarters", "ceo"]
    }
  }
}
{
  "company": {
    "name": "TechCorp Inc.",
    "headquarters": {
      "street": "100 Innovation Drive",
      "city": "San Francisco",
      "state": "CA",
      "postalCode": "94105",
      "country": "USA"
    },
    "ceo": {
      "name": "Jane Doe",
      "title": "Chief Executive Officer",
      "email": "[email protected]",
      "phone": "+1-555-0200"
    },
    "cto": {
      "name": "John Smith",
      "title": "Chief Technology Officer",
      "email": "[email protected]",
      "phone": "+1-555-0201"
    },
    "founded": 2010
  }
}

References in Arrays

Use references to define consistent item schemas in arrays:

{
  "type": "object",
  "properties": {
    "team": {
      "type": "array",
      "items": { "$ref": "#/$defs/employee" },
      "minItems": 1
    }
  },
  "required": ["team"],
  "$defs": {
    "employee": {
      "type": "object",
      "properties": {
        "id": { "type": "string", "pattern": "^EMP-[0-9]{6}$" },
        "name": { "type": "string" },
        "department": {
          "type": "string",
          "enum": ["Engineering", "Sales", "Marketing", "HR", "Finance"]
        },
        "level": {
          "type": "string",
          "enum": ["Junior", "Mid", "Senior", "Lead", "Principal"]
        },
        "skills": {
          "type": "array",
          "items": { "type": "string" },
          "minItems": 1,
          "maxItems": 10
        }
      },
      "required": ["id", "name", "department", "level"]
    }
  }
}
{
  "team": [
    {
      "id": "EMP-001234",
      "name": "Alice Chen",
      "department": "Engineering",
      "level": "Senior",
      "skills": ["Python", "JavaScript", "Docker", "Kubernetes"]
    },
    {
      "id": "EMP-001235",
      "name": "Bob Wilson",
      "department": "Engineering",
      "level": "Mid",
      "skills": ["Java", "Spring", "PostgreSQL"]
    },
    {
      "id": "EMP-001236",
      "name": "Carol Davis",
      "department": "Marketing",
      "level": "Lead",
      "skills": ["SEO", "Content Strategy", "Analytics"]
    }
  ]
}

  Important

dotjson only supports internal references (within the same schema). External references like file:// or http:// are not supported.

Recursive Schemas

Recursive schemas allow structures to reference themselves, enabling arbitrarily nested data like trees, graphs, and hierarchies.

Simple Recursion

A basic tree structure with self-referencing nodes:

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "value": { "type": "number" },
    "children": {
      "type": "array",
      "items": { "$ref": "#" },
      "default": []
    }
  },
  "required": ["name", "value"]
}
{
  "name": "root",
  "value": 100,
  "children": [
    {
      "name": "branch1",
      "value": 50,
      "children": [
        {
          "name": "leaf1",
          "value": 25,
          "children": []
        },
        {
          "name": "leaf2",
          "value": 25,
          "children": []
        }
      ]
    },
    {
      "name": "branch2",
      "value": 50,
      "children": []
    }
  ]
}

File System Structure

Model hierarchical file systems with recursive schemas:

{
  "$defs": {
    "file": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "type": { "type": "string", "const": "file" },
        "size": { "type": "integer", "minimum": 0 },
        "modified": { "type": "string", "format": "date-time" }
      },
      "required": ["name", "type", "size"]
    },
    "directory": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "type": { "type": "string", "const": "directory" },
        "contents": {
          "type": "array",
          "items": {
            "anyOf": [
              { "$ref": "#/$defs/file" },
              { "$ref": "#/$defs/directory" }
            ]
          }
        }
      },
      "required": ["name", "type", "contents"]
    }
  },
  "$ref": "#/$defs/directory"
}
{
  "name": "project",
  "type": "directory",
  "contents": [
    {
      "name": "src",
      "type": "directory",
      "contents": [
        {
          "name": "main.js",
          "type": "file",
          "size": 2048,
          "modified": "2024-03-15T10:30:00Z"
        },
        {
          "name": "utils",
          "type": "directory",
          "contents": [
            {
              "name": "helpers.js",
              "type": "file",
              "size": 1024,
              "modified": "2024-03-14T15:45:00Z"
            }
          ]
        }
      ]
    },
    {
      "name": "README.md",
      "type": "file",
      "size": 4096,
      "modified": "2024-03-15T09:00:00Z"
    }
  ]
}

Knowledge Graph

Create interconnected concept networks:

{
  "type": "object",
  "properties": {
    "concept": { "type": "string" },
    "definition": { "type": "string", "maxLength": 200 },
    "category": {
      "type": "string",
      "enum": ["fundamental", "derived", "application"]
    },
    "relatedConcepts": {
      "type": "array",
      "items": { "$ref": "#" },
      "maxItems": 3,
      "default": []
    }
  },
  "required": ["concept", "definition", "category"]
}
{
  "concept": "Machine Learning",
  "definition": "A subset of AI where computers learn from data without explicit programming",
  "category": "fundamental",
  "relatedConcepts": [
    {
      "concept": "Neural Networks",
      "definition": "Computing systems inspired by biological neural networks",
      "category": "derived",
      "relatedConcepts": [
        {
          "concept": "Deep Learning",
          "definition": "Neural networks with multiple layers for complex pattern recognition",
          "category": "application",
          "relatedConcepts": []
        }
      ]
    },
    {
      "concept": "Training Data",
      "definition": "Labeled examples used to teach machine learning models",
      "category": "fundamental",
      "relatedConcepts": []
    }
  ]
}

  Note

Complex recursive schemas can be slow to compile. Consider caching compiled schemas for better performance.

Choice with anyOf

anyOf allows the model to choose from multiple possible schemas, enabling flexible data structures.

Primitive Type Choice

Use when a single field may be represented in multiple primitive encodings (for example, a UUID string or a numeric ID).

{
  "type": "object",
  "properties": {
    "identifier": {
      "anyOf": [
        { "type": "string", "format": "uuid" },
        { "type": "integer", "minimum": 1 }
      ],
      "description": "UUID or numeric ID"
    },
    "timestamp": {
      "anyOf": [
        { "type": "string", "format": "date-time" },
        { "type": "integer", "minimum": 0 }
      ],
      "description": "ISO date or Unix timestamp"
    }
  },
  "required": ["identifier", "timestamp"]
}

Using UUID and ISO date:

{
  "identifier": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2024-03-15T10:30:00Z"
}

Using integer ID and Unix timestamp:

{
  "identifier": 12345,
  "timestamp": 1710499800
}

Discriminated Object Variants (Tagged Unions)

Use when the overall object shape differs; include a discriminator field (such as a tag or a success flag) to select the active variant.

{
  "type": "object",
  "properties": {
    "status": { "type": "integer" },
    "response": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "success": { "type": "boolean", "const": true },
            "data": {
              "type": "object",
              "properties": {
                "id": { "type": "string" },
                "result": { "type": "string" }
              },
              "required": ["id", "result"]
            }
          },
          "required": ["success", "data"]
        },
        {
          "type": "object",
          "properties": {
            "success": { "type": "boolean", "const": false },
            "error": {
              "type": "object",
              "properties": {
                "code": { "type": "string" },
                "message": { "type": "string" },
                "details": { "type": "string" }
              },
              "required": ["code", "message"]
            }
          },
          "required": ["success", "error"]
        }
      ]
    }
  },
  "required": ["status", "response"]
}

Success response:

{
  "status": 200,
  "response": {
    "success": true,
    "data": {
      "id": "req-123",
      "result": "Operation completed successfully"
    }
  }
}

Error response:

{
  "status": 400,
  "response": {
    "success": false,
    "error": {
      "code": "INVALID_INPUT",
      "message": "The provided data is invalid",
      "details": "Email field must be a valid email address"
    }
  }
}

Polymorphic Data

Handle different object types in the same field:

{
  "type": "object",
  "properties": {
    "events": {
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "type": { "type": "string", "const": "click" },
              "timestamp": { "type": "integer" },
              "x": { "type": "integer" },
              "y": { "type": "integer" },
              "element": { "type": "string" }
            },
            "required": ["type", "timestamp", "x", "y", "element"]
          },
          {
            "type": "object",
            "properties": {
              "type": { "type": "string", "const": "pageview" },
              "timestamp": { "type": "integer" },
              "url": { "type": "string", "format": "uri" },
              "referrer": { "type": "string" }
            },
            "required": ["type", "timestamp", "url"]
          },
          {
            "type": "object",
            "properties": {
              "type": { "type": "string", "const": "form_submit" },
              "timestamp": { "type": "integer" },
              "formId": { "type": "string" },
              "fields": {
                "type": "object",
                "additionalProperties": false
              }
            },
            "required": ["type", "timestamp", "formId", "fields"]
          }
        ]
      }
    }
  },
  "required": ["events"]
}
{
  "events": [
    {
      "type": "pageview",
      "timestamp": 1710499800,
      "url": "https://example.com/products",
      "referrer": "https://google.com"
    },
    {
      "type": "click",
      "timestamp": 1710499810,
      "x": 450,
      "y": 320,
      "element": "button#add-to-cart"
    },
    {
      "type": "form_submit",
      "timestamp": 1710499820,
      "formId": "checkout-form",
      "fields": {
        "email": "[email protected]",
        "quantity": "2"
      }
    }
  ]
}

Next Steps