Skip to main content

Overview

Response schemas ensure your SnakeQuery results have consistent structure and data types. Instead of receiving free-form responses, schemas guarantee specific formats that your applications can rely on.
Why Use Schemas? Schemas provide type safety, validation, and consistency across all your queries, making your code more reliable and maintainable.

Basic Schema Structure

All SnakeQuery schemas follow the JSON Schema specification:
{
  "type": "object|array|string|number|boolean",
  "properties": { /* object properties */ },
  "items": { /* array item definition */ },
  "required": ["field1", "field2"],
  "minimum": 0,
  "maximum": 1000
}

Simple Data Types

String Schema

{
  "type": "string",
  "minLength": 1,
  "maxLength": 100
}
Example Response:
"iPhone 14 Pro"

Number Schema

{
  "type": "number",
  "minimum": 0,
  "maximum": 10000
}
Example Response:
999.99

Boolean Schema

{
  "type": "boolean"
}
Example Response:
true

Object Schemas

Basic Object

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "price": { "type": "number", "minimum": 0 },
    "inStock": { "type": "boolean" }
  },
  "required": ["name", "price"]
}
Example Response:
{
  "name": "MacBook Pro",
  "price": 2399,
  "inStock": true
}

Nested Object

{
  "type": "object",
  "properties": {
    "product": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "price": { "type": "number", "minimum": 0 }
      },
      "required": ["name", "price"]
    },
    "customer": {
      "type": "object", 
      "properties": {
        "email": { "type": "string" },
        "phone": { "type": "string" }
      }
    }
  },
  "required": ["product"]
}
Example Response:
{
  "product": {
    "name": "iPhone 14",
    "price": 999
  },
  "customer": {
    "email": "user@example.com",
    "phone": "+1-555-0123"
  }
}

Array Schemas

Array of Simple Types

{
  "type": "array",
  "items": { "type": "string" },
  "minItems": 1,
  "maxItems": 10
}
Example Response:
["electronics", "computers", "phones"]

Array of Objects

{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "productName": { "type": "string" },
      "price": { "type": "number", "minimum": 0 },
      "category": { "type": "string" }
    },
    "required": ["productName", "price"]
  }
}
Example Response:
[
  {
    "productName": "iPhone 14",
    "price": 999,
    "category": "electronics"
  },
  {
    "productName": "MacBook Air", 
    "price": 1299,
    "category": "computers"
  }
]

Advanced Schema Patterns

Summary with Details

Perfect for analytics queries that need both aggregate data and individual items:
{
  "type": "object",
  "properties": {
    "summary": {
      "type": "object",
      "properties": {
        "totalProducts": { "type": "integer", "minimum": 0 },
        "averagePrice": { "type": "number", "minimum": 0 },
        "categories": {
          "type": "array",
          "items": { "type": "string" }
        }
      },
      "required": ["totalProducts", "averagePrice"]
    },
    "products": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "price": { "type": "number", "minimum": 0 },
          "category": { "type": "string" }
        },
        "required": ["name", "price"]
      }
    }
  },
  "required": ["summary", "products"]
}
Query Example:
const result = await client.query({
  query: 'Analyze product catalog - show summary statistics and list all products under $500',
  data: products,
  responseSchema: summarySchema
});
Example Response:
{
  "summary": {
    "totalProducts": 25,
    "averagePrice": 287.50,
    "categories": ["electronics", "home", "fashion"]
  },
  "products": [
    {
      "name": "Wireless Headphones",
      "price": 199,
      "category": "electronics"
    },
    {
      "name": "Coffee Maker",
      "price": 89,
      "category": "home"
    }
  ]
}

Grouped Data

Ideal for categorization and grouping queries:
{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "category": { "type": "string" },
      "count": { "type": "integer", "minimum": 0 },
      "averagePrice": { "type": "number", "minimum": 0 },
      "items": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "price": { "type": "number", "minimum": 0 }
          },
          "required": ["name", "price"]
        }
      }
    },
    "required": ["category", "count", "items"]
  }
}
Query Example:
const result = await client.query({
  query: 'Group products by category, show count and average price for each',
  data: products,
  responseSchema: groupedSchema
});
Example Response:
[
  {
    "category": "electronics",
    "count": 12,
    "averagePrice": 549.99,
    "items": [
      { "name": "iPhone 14", "price": 999 },
      { "name": "AirPods", "price": 179 }
    ]
  },
  {
    "category": "home",
    "count": 8,
    "averagePrice": 67.50,
    "items": [
      { "name": "Coffee Mug", "price": 19 },
      { "name": "Lamp", "price": 85 }
    ]
  }
]

Time-Series Data

Perfect for analytics with date/time components:
{
  "type": "object",
  "properties": {
    "period": {
      "type": "object",
      "properties": {
        "startDate": { "type": "string" },
        "endDate": { "type": "string" }
      }
    },
    "metrics": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "date": { "type": "string" },
          "revenue": { "type": "number", "minimum": 0 },
          "orders": { "type": "integer", "minimum": 0 },
          "averageOrderValue": { "type": "number", "minimum": 0 }
        },
        "required": ["date", "revenue", "orders"]
      }
    },
    "trends": {
      "type": "object",
      "properties": {
        "revenueGrowth": { "type": "number" },
        "direction": { "type": "string", "enum": ["up", "down", "stable"] }
      }
    }
  },
  "required": ["metrics"]
}

SDK-Specific Schema Building

Node.js SDK

const { SchemaBuilder } = require('snake-query');

// Simple product schema
const productSchema = SchemaBuilder.create()
  .array(
    SchemaBuilder.create()
      .object()
      .addStringProperty('name')
      .addNumberProperty('price', { minimum: 0 })
      .addStringProperty('category')
      .required(['name', 'price'])
      .build()
  )
  .build();

// Complex analytics schema  
const analyticsSchema = SchemaBuilder.create()
  .object()
  .addObjectProperty('summary', {
    totalItems: { type: 'integer', minimum: 0 },
    averageValue: { type: 'number', minimum: 0 }
  })
  .addArrayProperty('details', {
    type: 'object',
    properties: {
      category: { type: 'string' },
      count: { type: 'integer' },
      items: {
        type: 'array',
        items: {
          type: 'object',
          properties: {
            name: { type: 'string' },
            value: { type: 'number' }
          }
        }
      }
    }
  })
  .required(['summary', 'details'])
  .build();

Python SDK

from snake_query_sdk import SchemaBuilder

# Simple product schema
product_schema = SchemaBuilder.create() \
    .array(
        SchemaBuilder.create() \
        .object() \
        .add_string_property('name') \
        .add_number_property('price', minimum=0) \
        .add_string_property('category') \
        .required(['name', 'price']) \
        .build()
    ) \
    .build()

# Complex analytics schema
analytics_schema = SchemaBuilder.create() \
    .object() \
    .add_object_property('summary', {
        'totalItems': {'type': 'integer', 'minimum': 0},
        'averageValue': {'type': 'number', 'minimum': 0}
    }) \
    .add_array_property('details', {
        'type': 'object',
        'properties': {
            'category': {'type': 'string'},
            'count': {'type': 'integer'},
            'items': {
                'type': 'array',
                'items': {
                    'type': 'object',
                    'properties': {
                        'name': {'type': 'string'},
                        'value': {'type': 'number'}
                    }
                }
            }
        }
    }) \
    .required(['summary', 'details']) \
    .build()

Fetch API (Raw JSON)

const productSchema = {
  type: 'array',
  items: {
    type: 'object',
    properties: {
      name: { type: 'string' },
      price: { type: 'number', minimum: 0 },
      category: { type: 'string' }
    },
    required: ['name', 'price']
  }
};

const analyticsSchema = {
  type: 'object',
  properties: {
    summary: {
      type: 'object',
      properties: {
        totalItems: { type: 'integer', minimum: 0 },
        averageValue: { type: 'number', minimum: 0 }
      }
    },
    details: {
      type: 'array',
      items: {
        type: 'object',
        properties: {
          category: { type: 'string' },
          count: { type: 'integer' },
          items: {
            type: 'array',
            items: {
              type: 'object',
              properties: {
                name: { type: 'string' },
                value: { type: 'number' }
              }
            }
          }
        }
      }
    }
  },
  required: ['summary', 'details']
};

Best Practices

1. Always Define Required Fields

{
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "price": { "type": "number" },
    "description": { "type": "string" }
  },
  "required": ["name", "price"]
}
This ensures critical fields are always present in responses.

2. Use Appropriate Constraints

{
  "type": "object",
  "properties": {
    "price": { 
      "type": "number", 
      "minimum": 0,
      "maximum": 999999 
    },
    "rating": { 
      "type": "number", 
      "minimum": 1, 
      "maximum": 5 
    },
    "status": { 
      "type": "string", 
      "enum": ["active", "inactive", "pending"] 
    }
  }
}

3. Keep Schemas Simple

// ✅ Good - focused and clear
{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "productName": { "type": "string" },
      "price": { "type": "number", "minimum": 0 }
    },
    "required": ["productName", "price"]
  }
}

// ❌ Avoid - overly complex
{
  "type": "object",
  "properties": {
    "data": {
      "type": "object", 
      "properties": {
        "meta": {
          "type": "object",
          "properties": {
            "nested": {
              "type": "object",
              // Too many levels deep...
            }
          }
        }
      }
    }
  }
}

4. Use Descriptive Property Names

// ✅ Clear property names
{
  "type": "object",
  "properties": {
    "productName": { "type": "string" },
    "unitPrice": { "type": "number" },
    "isAvailable": { "type": "boolean" },
    "categoryName": { "type": "string" }
  }
}

// ❌ Unclear abbreviations
{
  "type": "object", 
  "properties": {
    "pn": { "type": "string" },
    "up": { "type": "number" },
    "avail": { "type": "boolean" },
    "cat": { "type": "string" }
  }
}

Common Schema Patterns

E-commerce Product

{
  "type": "object",
  "properties": {
    "productId": { "type": "string" },
    "name": { "type": "string" },
    "price": { "type": "number", "minimum": 0 },
    "currency": { "type": "string", "enum": ["USD", "EUR", "GBP"] },
    "category": { "type": "string" },
    "brand": { "type": "string" },
    "inStock": { "type": "boolean" },
    "rating": { "type": "number", "minimum": 1, "maximum": 5 },
    "reviewCount": { "type": "integer", "minimum": 0 }
  },
  "required": ["productId", "name", "price", "currency"]
}

User Profile

{
  "type": "object",
  "properties": {
    "userId": { "type": "string" },
    "username": { "type": "string" },
    "email": { "type": "string" },
    "profile": {
      "type": "object",
      "properties": {
        "firstName": { "type": "string" },
        "lastName": { "type": "string" },
        "dateJoined": { "type": "string" },
        "isActive": { "type": "boolean" }
      }
    },
    "preferences": {
      "type": "object",
      "properties": {
        "newsletter": { "type": "boolean" },
        "notifications": { "type": "boolean" }
      }
    }
  },
  "required": ["userId", "username", "email"]
}

Sales Analytics

{
  "type": "object",
  "properties": {
    "period": {
      "type": "object",
      "properties": {
        "startDate": { "type": "string" },
        "endDate": { "type": "string" }
      }
    },
    "totals": {
      "type": "object", 
      "properties": {
        "revenue": { "type": "number", "minimum": 0 },
        "orders": { "type": "integer", "minimum": 0 },
        "customers": { "type": "integer", "minimum": 0 }
      }
    },
    "breakdown": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "category": { "type": "string" },
          "revenue": { "type": "number", "minimum": 0 },
          "percentage": { "type": "number", "minimum": 0, "maximum": 100 }
        }
      }
    }
  },
  "required": ["totals", "breakdown"]
}

Testing Your Schemas

Schema Validation

Before using schemas in production, test them with sample data:
// Test with expected data structure
const testData = {
  productName: "iPhone 14",
  price: 999,
  category: "electronics"
};

// This should match your schema structure
const result = await client.query({
  query: 'Format this product data',
  data: [testData],
  responseSchema: productSchema
});

console.log('Schema validation passed:', result.response);

Iterative Improvement

Start with basic schemas and refine them based on actual query results:
// Version 1 - Basic
const basicSchema = {
  type: 'array',
  items: {
    type: 'object',
    properties: {
      name: { type: 'string' },
      price: { type: 'number' }
    }
  }
};

// Version 2 - Add constraints after testing
const improvedSchema = {
  type: 'array',
  items: {
    type: 'object',
    properties: {
      name: { type: 'string', minLength: 1 },
      price: { type: 'number', minimum: 0, maximum: 100000 }
    },
    required: ['name', 'price']
  }
};

Next Steps

I